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:
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform.c179
-rw-r--r--source/blender/editors/transform/transform.h63
-rw-r--r--source/blender/editors/transform/transform_constraints.c16
-rw-r--r--source/blender/editors/transform/transform_convert.c240
-rw-r--r--source/blender/editors/transform/transform_convert.h7
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c3
-rw-r--r--source/blender/editors/transform/transform_convert_cursor.c26
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c8
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c10
-rw-r--r--source/blender/editors/transform/transform_convert_lattice.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mball.c20
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c1216
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_skin.c30
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_uv.c2
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c4
-rw-r--r--source/blender/editors/transform/transform_generics.c25
-rw-r--r--source/blender/editors/transform/transform_mode.c37
-rw-r--r--source/blender/editors/transform/transform_mode.h1
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c1
-rw-r--r--source/blender/editors/transform/transform_mode_edge_rotate_normal.c2
-rw-r--r--source/blender/editors/transform/transform_mode_gpopacity.c1
-rw-r--r--source/blender/editors/transform/transform_mode_gpshrinkfatten.c1
-rw-r--r--source/blender/editors/transform/transform_mode_maskshrinkfatten.c1
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c3
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c3
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c2
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c2
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c1
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c3
-rw-r--r--source/blender/editors/transform/transform_orientations.c6
30 files changed, 1004 insertions, 911 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 2fbcbe22349..17bfc23aea7 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -74,7 +74,7 @@
static void drawTransformApply(const struct bContext *C, ARegion *region, void *arg);
-static void initSnapSpatial(TransInfo *t, float r_snap[3]);
+static void initSnapSpatial(TransInfo *t, float r_snap[2]);
bool transdata_check_local_islands(TransInfo *t, short around)
{
@@ -724,81 +724,92 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
{
- if (!(t->flag & T_NO_CONSTRAINT)) {
- if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) {
+ if (t->flag & T_NO_CONSTRAINT) {
+ return false;
+ }
+
+ if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) {
+ return false;
+ }
+
+ int constraint_curr = -1;
+
+ if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) {
+ t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE);
+
+ /* Avoid changing orientation in this case. */
+ constraint_curr = -2;
+ }
+ else if (t->con.mode & CON_APPLY) {
+ constraint_curr = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+ }
+
+ int constraint_new;
+ const char *msg_2d = "", *msg_3d = "";
+
+ /* Initialize */
+ switch (modal_type) {
+ case TFM_MODAL_AXIS_X:
+ msg_2d = TIP_("along X");
+ msg_3d = TIP_("along %s X");
+ constraint_new = CON_AXIS0;
+ break;
+ case TFM_MODAL_AXIS_Y:
+ msg_2d = TIP_("along Y");
+ msg_3d = TIP_("along %s Y");
+ constraint_new = CON_AXIS1;
+ break;
+ case TFM_MODAL_AXIS_Z:
+ msg_2d = TIP_("along Z");
+ msg_3d = TIP_("along %s Z");
+ constraint_new = CON_AXIS2;
+ break;
+ case TFM_MODAL_PLANE_X:
+ msg_3d = TIP_("locking %s X");
+ constraint_new = CON_AXIS1 | CON_AXIS2;
+ break;
+ case TFM_MODAL_PLANE_Y:
+ msg_3d = TIP_("locking %s Y");
+ constraint_new = CON_AXIS0 | CON_AXIS2;
+ break;
+ case TFM_MODAL_PLANE_Z:
+ msg_3d = TIP_("locking %s Z");
+ constraint_new = CON_AXIS0 | CON_AXIS1;
+ break;
+ default:
+ /* Invalid key */
return false;
- }
- int constraint_curr = (t->con.mode & CON_APPLY) ?
- t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2) :
- -1;
- int constraint_new;
- const char *msg_2d = "", *msg_3d = "";
+ }
- /* Initialize */
- switch (modal_type) {
- case TFM_MODAL_AXIS_X:
- msg_2d = TIP_("along X");
- msg_3d = TIP_("along %s X");
- constraint_new = CON_AXIS0;
- break;
- case TFM_MODAL_AXIS_Y:
- msg_2d = TIP_("along Y");
- msg_3d = TIP_("along %s Y");
- constraint_new = CON_AXIS1;
- break;
- case TFM_MODAL_AXIS_Z:
- msg_2d = TIP_("along Z");
- msg_3d = TIP_("along %s Z");
- constraint_new = CON_AXIS2;
- break;
- case TFM_MODAL_PLANE_X:
- msg_3d = TIP_("locking %s X");
- constraint_new = CON_AXIS1 | CON_AXIS2;
- break;
- case TFM_MODAL_PLANE_Y:
- msg_3d = TIP_("locking %s Y");
- constraint_new = CON_AXIS0 | CON_AXIS2;
- break;
- case TFM_MODAL_PLANE_Z:
- msg_3d = TIP_("locking %s Z");
- constraint_new = CON_AXIS0 | CON_AXIS1;
- break;
- default:
- /* Invalid key */
- return false;
+ if (t->flag & T_2D_EDIT) {
+ BLI_assert(modal_type < TFM_MODAL_PLANE_X);
+ if (constraint_new == CON_AXIS2) {
+ return false;
}
-
- if (t->flag & T_2D_EDIT) {
- BLI_assert(modal_type < TFM_MODAL_PLANE_X);
- if (constraint_new == CON_AXIS2) {
- return false;
- }
- if (constraint_curr == constraint_new) {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, constraint_new, msg_2d);
- }
+ if (constraint_curr == constraint_new) {
+ stopConstraint(t);
}
else {
- short orient_index = 1;
- if (t->orient_curr == 0 || ELEM(constraint_curr, -1, constraint_new)) {
- /* Successive presses on existing axis, cycle orientation modes. */
- orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
- }
+ setUserConstraint(t, constraint_new, msg_2d);
+ }
+ }
+ else {
+ short orient_index = 1;
+ if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) {
+ /* Successive presses on existing axis, cycle orientation modes. */
+ orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
+ }
- transform_orientations_current_set(t, orient_index);
- if (orient_index == 0) {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, constraint_new, msg_3d);
- }
+ transform_orientations_current_set(t, orient_index);
+ if (orient_index == 0) {
+ stopConstraint(t);
+ }
+ else {
+ setUserConstraint(t, constraint_new, msg_3d);
}
- t->redraw |= TREDRAW_HARD;
- return true;
}
- return false;
+ t->redraw |= TREDRAW_HARD;
+ return true;
}
int transformEvent(TransInfo *t, const wmEvent *event)
@@ -814,7 +825,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
else if (event->type == MOUSEMOVE) {
- if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) {
+ if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) {
t->con.mode |= CON_SELECT;
}
@@ -1062,10 +1073,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
t->state = TRANS_CONFIRM;
}
else if ((t->flag & T_NO_CONSTRAINT) == 0) {
- if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) {
+ if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) {
/* Confirm. */
postSelectConstraint(t);
- t->modifiers &= ~(MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE);
+ t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE);
}
else {
if (t->options & CTX_CAMERA) {
@@ -1079,8 +1090,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
else {
- t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ? MOD_CONSTRAINT_SELECT :
- MOD_CONSTRAINT_PLANE;
+ t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ?
+ MOD_CONSTRAINT_SELECT_AXIS :
+ MOD_CONSTRAINT_SELECT_PLANE;
if (t->con.mode & CON_APPLY) {
stopConstraint(t);
}
@@ -1412,25 +1424,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
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
- * 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;
- }
-
/* Save back mode in case we're in the generic operator */
if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
RNA_property_enum_set(op->ptr, prop, t->mode);
@@ -1638,7 +1631,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2])
/**
* \note caller needs to free 't' on a 0 return
- * \warning \a event might be NULL (when tweaking from redo panel)
+ * \warning \a event might be NULL (when tweaking from redo panel)
* \see #saveTransform which writes these values back.
*/
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index f2d5800abb7..f03defe26e2 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -88,12 +88,11 @@ typedef enum {
CTX_TEXTURE_SPACE = (1 << 9),
CTX_NO_PET = (1 << 10),
- CTX_NO_MIRROR = (1 << 11),
- CTX_AUTOCONFIRM = (1 << 12),
+ CTX_AUTOCONFIRM = (1 << 11),
/** When transforming object's, adjust the object data so it stays in the same place. */
- CTX_OBMODE_XFORM_OBDATA = (1 << 13),
+ CTX_OBMODE_XFORM_OBDATA = (1 << 12),
/** Transform object parents without moving their children. */
- CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 14),
+ CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 13),
} eTContext;
/** #TransInfo.flag */
@@ -105,60 +104,59 @@ typedef enum {
/** restrictions flags */
T_NO_CONSTRAINT = 1 << 2,
T_NULL_ONE = 1 << 3,
- T_NO_ZERO = 1 << 4,
- T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
+ T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE,
- T_PROP_EDIT = 1 << 5,
- T_PROP_CONNECTED = 1 << 6,
- T_PROP_PROJECTED = 1 << 7,
+ T_PROP_EDIT = 1 << 4,
+ T_PROP_CONNECTED = 1 << 5,
+ T_PROP_PROJECTED = 1 << 6,
T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
- T_V3D_ALIGN = 1 << 8,
+ T_V3D_ALIGN = 1 << 7,
/** For 2D views such as UV or f-curve. */
- T_2D_EDIT = 1 << 9,
- T_CLIP_UV = 1 << 10,
+ T_2D_EDIT = 1 << 8,
+ T_CLIP_UV = 1 << 9,
/** Auto-IK is on. */
- T_AUTOIK = 1 << 11,
+ T_AUTOIK = 1 << 10,
/** Don't use mirror even if the data-block option is set. */
- T_NO_MIRROR = 1 << 12,
+ T_NO_MIRROR = 1 << 11,
/** To indicate that the value set in the `value` parameter is the final
* value of the transformation, modified only by the constrain. */
- T_INPUT_IS_VALUES_FINAL = 1 << 13,
+ T_INPUT_IS_VALUES_FINAL = 1 << 12,
/** To specify if we save back settings at the end. */
- T_MODAL = 1 << 14,
+ T_MODAL = 1 << 13,
/** No re-topology (projection). */
- T_NO_PROJECT = 1 << 15,
+ T_NO_PROJECT = 1 << 14,
- T_RELEASE_CONFIRM = 1 << 16,
+ T_RELEASE_CONFIRM = 1 << 15,
/** Alternative transformation. used to add offset to tracking markers. */
- T_ALT_TRANSFORM = 1 << 17,
+ T_ALT_TRANSFORM = 1 << 16,
/** #TransInfo.center has been set, don't change it. */
- T_OVERRIDE_CENTER = 1 << 18,
+ T_OVERRIDE_CENTER = 1 << 17,
- T_MODAL_CURSOR_SET = 1 << 19,
+ T_MODAL_CURSOR_SET = 1 << 18,
- T_CLNOR_REBUILD = 1 << 20,
+ T_CLNOR_REBUILD = 1 << 19,
/** Merges unselected into selected after transforming (runs after transforming). */
- T_AUTOMERGE = 1 << 21,
+ T_AUTOMERGE = 1 << 20,
/** Runs auto-merge & splits. */
- T_AUTOSPLIT = 1 << 22,
+ T_AUTOSPLIT = 1 << 21,
} eTFlag;
/** #TransInfo.modifiers */
typedef enum {
- MOD_CONSTRAINT_SELECT = 1 << 0,
+ MOD_CONSTRAINT_SELECT_AXIS = 1 << 0,
MOD_PRECISION = 1 << 1,
MOD_SNAP = 1 << 2,
MOD_SNAP_INVERT = 1 << 3,
- MOD_CONSTRAINT_PLANE = 1 << 4,
+ MOD_CONSTRAINT_SELECT_PLANE = 1 << 4,
} eTModifier;
/** #TransSnap.status */
@@ -432,14 +430,14 @@ typedef struct TransCustomDataContainer {
/**
* Container for Transform Data
*
- * Used to implement multi-object modes, so each object can have it's
+ * Used to implement multi-object modes, so each object can have its
* own data array as well as object matrix, local center etc.
*
* Anything that can't be shared between all objects
* and doesn't make sense to store for every vertex (in the #TransDataContainer.data).
*
* \note at some point this could be used to store non object containers
- * although this only makes sense if each container has it's own matrices,
+ * although this only makes sense if each container has its own matrices,
* otherwise all elements may as well be stored in one array (#TransDataContainer.data),
* as is already done for curve-objects, f-curves. etc.
*/
@@ -598,11 +596,18 @@ typedef struct TransInfo {
* mouse button then.) */
bool is_launch_event_tweak;
+ bool is_orient_set;
+
struct {
short type;
float matrix[3][3];
} orient[3];
- short orient_curr;
+
+ enum {
+ O_DEFAULT = 0,
+ O_SCENE,
+ O_SET,
+ } orient_curr;
/** backup from view3d, to restore on end. */
short gizmo_flag;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 2037981e655..8c74d5349ba 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -953,9 +953,8 @@ void startConstraint(TransInfo *t)
void stopConstraint(TransInfo *t)
{
- if (t->orient_curr != 0) {
- t->orient_curr = 0;
- transform_orientations_current_set(t, t->orient_curr);
+ if (t->orient_curr != O_DEFAULT) {
+ transform_orientations_current_set(t, O_DEFAULT);
}
t->con.mode &= ~(CON_APPLY | CON_SELECT);
@@ -971,12 +970,11 @@ void stopConstraint(TransInfo *t)
void initSelectConstraint(TransInfo *t)
{
- if (t->orient_curr == 0) {
- transform_orientations_current_set(t, 1);
+ if (t->orient_curr == O_DEFAULT) {
+ transform_orientations_current_set(t, O_SCENE);
}
setUserConstraint(t, CON_APPLY | CON_SELECT, "%s");
- setNearestAxis(t);
}
void selectConstraint(TransInfo *t)
@@ -1063,7 +1061,7 @@ static void setNearestAxis3d(TransInfo *t)
}
if (len[0] <= len[1] && len[0] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) {
t->con.mode |= (CON_AXIS1 | CON_AXIS2);
BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s X axis"), t->spacename);
}
@@ -1073,7 +1071,7 @@ static void setNearestAxis3d(TransInfo *t)
}
}
else if (len[1] <= len[0] && len[1] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) {
t->con.mode |= (CON_AXIS0 | CON_AXIS2);
BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s Y axis"), t->spacename);
}
@@ -1083,7 +1081,7 @@ static void setNearestAxis3d(TransInfo *t)
}
}
else if (len[2] <= len[1] && len[2] <= len[0]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT_PLANE) {
t->con.mode |= (CON_AXIS0 | CON_AXIS1);
BLI_snprintf(t->con.text, sizeof(t->con.text), TIP_(" locking %s Z axis"), t->spacename);
}
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index c021c084a23..b4175faacf4 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -37,6 +37,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -505,9 +506,27 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
bool clipx = true, clipy = true;
float min[2], max[2];
- min[0] = min[1] = 0.0f;
- max[0] = t->aspect[0];
- max[1] = t->aspect[1];
+ /* Check if the current image in UV editor is a tiled image or not. */
+ const SpaceImage *sima = t->area->spacedata.first;
+ const Image *image = sima->image;
+ const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+ /* Stores the coordinates of the closest UDIM tile.
+ * Also acts as an offset to the tile from the origin of UV space. */
+ float base_offset[2] = {0.0f, 0.0f};
+
+ /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
+ if (is_tiled_image) {
+ int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
+ if (nearest_tile_index != -1) {
+ nearest_tile_index -= 1001;
+ /* Getting coordinates of nearest tile from the tile index. */
+ base_offset[0] = nearest_tile_index % 10;
+ base_offset[1] = nearest_tile_index / 10;
+ }
+ }
+
+ min[0] = min[1] = FLT_MAX;
+ max[0] = max[1] = FLT_MIN;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
@@ -520,42 +539,48 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
}
if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ if (min[0] < base_offset[0] && t->center_global[0] > base_offset[0] &&
+ t->center_global[0] < base_offset[0] + (t->aspect[0] * 0.5f)) {
+ vec[0] *= (t->center_global[0] - base_offset[0]) / (t->center_global[0] - min[0]);
}
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ else if (max[0] > (base_offset[0] + t->aspect[0]) &&
+ t->center_global[0] < (base_offset[0] + t->aspect[0])) {
+ vec[0] *= (t->center_global[0] - (base_offset[0] + t->aspect[0])) /
+ (t->center_global[0] - max[0]);
}
else {
clipx = 0;
}
- if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ if (min[1] < base_offset[1] && t->center_global[1] > base_offset[1] &&
+ t->center_global[1] < base_offset[1] + (t->aspect[1] * 0.5f)) {
+ vec[1] *= (t->center_global[1] - base_offset[1]) / (t->center_global[1] - min[1]);
}
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
+ else if (max[1] > (base_offset[1] + t->aspect[1]) &&
+ t->center_global[1] < (base_offset[1] + t->aspect[1])) {
+ vec[1] *= (t->center_global[1] - (base_offset[1] + t->aspect[1])) /
+ (t->center_global[1] - max[1]);
}
else {
clipy = 0;
}
}
else {
- if (min[0] < 0.0f) {
- vec[0] -= min[0];
+ if (min[0] < base_offset[0]) {
+ vec[0] += base_offset[0] - min[0];
}
- else if (max[0] > t->aspect[0]) {
- vec[0] -= max[0] - t->aspect[0];
+ else if (max[0] > base_offset[0] + t->aspect[0]) {
+ vec[0] -= max[0] - base_offset[0] - t->aspect[0];
}
else {
clipx = 0;
}
- if (min[1] < 0.0f) {
- vec[1] -= min[1];
+ if (min[1] < base_offset[1]) {
+ vec[1] += base_offset[1] - min[1];
}
- else if (max[1] > t->aspect[1]) {
- vec[1] -= max[1] - t->aspect[1];
+ else if (max[1] > base_offset[1] + t->aspect[1]) {
+ vec[1] -= max[1] - base_offset[1] - t->aspect[1];
}
else {
clipy = 0;
@@ -1122,8 +1147,7 @@ static void init_TransDataContainers(TransInfo *t,
for (int i = 0; i < objects_len; i++) {
TransDataContainer *tc = &t->data_container[i];
- if (((t->flag & T_NO_MIRROR) == 0) && ((t->options & CTX_NO_MIRROR) == 0) &&
- (objects[i]->type == OB_MESH)) {
+ if (!(t->flag & T_NO_MIRROR) && (objects[i]->type == OB_MESH)) {
tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0;
tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0;
tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0;
@@ -1472,91 +1496,89 @@ void createTransData(bContext *C, TransInfo *t)
/** \name Transform Data Recalc/Flush
* \{ */
-void clipMirrorModifier(TransInfo *t)
+void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->obedit;
- ModifierData *md = ob->modifiers.first;
- float tolerance[3] = {0.0f, 0.0f, 0.0f};
- int axis = 0;
-
- for (; md; md = md->next) {
- if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData *)md;
-
- if (mmd->flag & MOD_MIR_CLIPPING) {
- axis = 0;
- if (mmd->flag & MOD_MIR_AXIS_X) {
- axis |= 1;
- tolerance[0] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Y) {
- axis |= 2;
- tolerance[1] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Z) {
- axis |= 4;
- tolerance[2] = mmd->tolerance;
- }
- if (axis) {
- float mtx[4][4], imtx[4][4];
- int i;
+ Object *ob = tc->obedit;
+ ModifierData *md = ob->modifiers.first;
+ float tolerance[3] = {0.0f, 0.0f, 0.0f};
+ int axis = 0;
+
+ for (; md; md = md->next) {
+ if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+
+ if (mmd->flag & MOD_MIR_CLIPPING) {
+ axis = 0;
+ if (mmd->flag & MOD_MIR_AXIS_X) {
+ axis |= 1;
+ tolerance[0] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Y) {
+ axis |= 2;
+ tolerance[1] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Z) {
+ axis |= 4;
+ tolerance[2] = mmd->tolerance;
+ }
+ if (axis) {
+ float mtx[4][4], imtx[4][4];
+ int i;
- if (mmd->mirror_ob) {
- float obinv[4][4];
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obinv, ob->obmat);
- invert_m4_m4(imtx, mtx);
- }
+ invert_m4_m4(obinv, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, obinv, ob->obmat);
+ invert_m4_m4(imtx, mtx);
+ }
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- int clip;
- float loc[3], iloc[3];
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ int clip;
+ float loc[3], iloc[3];
- if (td->loc == NULL) {
- break;
- }
+ if (td->loc == NULL) {
+ break;
+ }
- if (td->flag & TD_SKIP) {
- continue;
- }
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
- copy_v3_v3(loc, td->loc);
- copy_v3_v3(iloc, td->iloc);
+ copy_v3_v3(loc, td->loc);
+ copy_v3_v3(iloc, td->iloc);
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, loc);
- mul_m4_v3(mtx, iloc);
- }
+ if (mmd->mirror_ob) {
+ mul_m4_v3(mtx, loc);
+ mul_m4_v3(mtx, iloc);
+ }
- clip = 0;
- if (axis & 1) {
- if (fabsf(iloc[0]) <= tolerance[0] || loc[0] * iloc[0] < 0.0f) {
- loc[0] = 0.0f;
- clip = 1;
- }
+ clip = 0;
+ if (axis & 1) {
+ if (fabsf(iloc[0]) <= tolerance[0] || loc[0] * iloc[0] < 0.0f) {
+ loc[0] = 0.0f;
+ clip = 1;
}
+ }
- if (axis & 2) {
- if (fabsf(iloc[1]) <= tolerance[1] || loc[1] * iloc[1] < 0.0f) {
- loc[1] = 0.0f;
- clip = 1;
- }
+ if (axis & 2) {
+ if (fabsf(iloc[1]) <= tolerance[1] || loc[1] * iloc[1] < 0.0f) {
+ loc[1] = 0.0f;
+ clip = 1;
}
- if (axis & 4) {
- if (fabsf(iloc[2]) <= tolerance[2] || loc[2] * iloc[2] < 0.0f) {
- loc[2] = 0.0f;
- clip = 1;
- }
+ }
+ if (axis & 4) {
+ if (fabsf(iloc[2]) <= tolerance[2] || loc[2] * iloc[2] < 0.0f) {
+ loc[2] = 0.0f;
+ clip = 1;
}
- if (clip) {
- if (mmd->mirror_ob) {
- mul_m4_v3(imtx, loc);
- }
- copy_v3_v3(td->loc, loc);
+ }
+ if (clip) {
+ if (mmd->mirror_ob) {
+ mul_m4_v3(imtx, loc);
}
+ copy_v3_v3(td->loc, loc);
}
}
}
@@ -1644,38 +1666,6 @@ void animrecord_check_state(TransInfo *t, struct Object *ob)
}
}
-static void recalcData_cursor_image(TransInfo *t)
-{
- TransDataContainer *tc = t->data_container;
- TransData *td = tc->data;
- float aspect_inv[2];
-
- aspect_inv[0] = 1.0f / t->aspect[0];
- aspect_inv[1] = 1.0f / t->aspect[1];
-
- td->loc[0] = td->loc[0] * aspect_inv[0];
- td->loc[1] = td->loc[1] * aspect_inv[1];
-
- DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
-}
-
-static void recalcData_cursor(TransInfo *t)
-{
- DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
-}
-
-static void recalcData_obedit(TransInfo *t)
-{
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- }
- }
-}
-
/* called for updating while transform acts, once per redraw */
void recalcData(TransInfo *t)
{
@@ -1742,7 +1732,7 @@ void recalcData(TransInfo *t)
recalcData_tracking(t);
break;
case TC_MBALL_VERTS:
- recalcData_obedit(t);
+ recalcData_mball(t);
break;
case TC_LATTICE_VERTS:
recalcData_lattice(t);
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 36a51d57f64..11550ec8803 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -45,7 +45,7 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
/* transform_convert_mesh.c */
-void mesh_customdatacorrect_init(TransInfo *t);
+void transform_convert_mesh_customdatacorrect_init(TransInfo *t);
/* transform_convert_sequencer.c */
int transform_convert_sequencer_get_snap_bound(TransInfo *t);
@@ -62,7 +62,7 @@ void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic);
struct TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt);
char transform_convert_frame_side_dir_get(TransInfo *t, float cframe);
bool FrameOnMouseSide(char side, float frame, float cframe);
-void clipMirrorModifier(TransInfo *t);
+void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc);
void animrecord_check_state(TransInfo *t, struct Object *ob);
/* transform_convert_action.c */
@@ -84,6 +84,8 @@ void special_aftertrans_update__pose(bContext *C, TransInfo *t);
/* transform_convert_cursor.c */
void createTransCursor_image(TransInfo *t);
void createTransCursor_view3d(TransInfo *t);
+void recalcData_cursor_image(TransInfo *t);
+void recalcData_cursor(TransInfo *t);
/* transform_convert_curve.c */
void createTransCurveVerts(TransInfo *t);
@@ -109,6 +111,7 @@ void special_aftertrans_update__mask(bContext *C, TransInfo *t);
/* transform_convert_mball.c */
void createTransMBallVerts(TransInfo *t);
+void recalcData_mball(TransInfo *t);
/* transform_convert_mesh.c */
struct TransIslandData {
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 7f24a0fa5f8..aaea9d05f84 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -1268,9 +1268,6 @@ void recalcData_edit_armature(TransInfo *t)
restoreBones(tc);
}
}
-
- /* Tag for redraw/invalidate overlay cache. */
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
}
}
diff --git a/source/blender/editors/transform/transform_convert_cursor.c b/source/blender/editors/transform/transform_convert_cursor.c
index 67d85f9610b..1f3eff31205 100644
--- a/source/blender/editors/transform/transform_convert_cursor.c
+++ b/source/blender/editors/transform/transform_convert_cursor.c
@@ -134,3 +134,29 @@ void createTransCursor_view3d(TransInfo *t)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Recalc Cursor
+ * \{ */
+
+void recalcData_cursor_image(TransInfo *t)
+{
+ TransDataContainer *tc = t->data_container;
+ TransData *td = tc->data;
+ float aspect_inv[2];
+
+ aspect_inv[0] = 1.0f / t->aspect[0];
+ aspect_inv[1] = 1.0f / t->aspect[1];
+
+ td->loc[0] = td->loc[0] * aspect_inv[0];
+ td->loc[1] = td->loc[1] * aspect_inv[1];
+
+ DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
+}
+
+void recalcData_cursor(TransInfo *t)
+{
+ DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 3ff83e00f43..e57fd85470f 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -441,7 +441,6 @@ void createTransCurveVerts(TransInfo *t)
void recalcData_curve(TransInfo *t)
{
if (t->state != TRANS_CANCEL) {
- clipMirrorModifier(t);
applyProject(t);
}
@@ -450,7 +449,7 @@ void recalcData_curve(TransInfo *t)
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
Nurb *nu = nurbs->first;
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
if (t->state == TRANS_CANCEL) {
while (nu) {
@@ -460,7 +459,10 @@ void recalcData_curve(TransInfo *t)
}
}
else {
- /* Normal updating */
+ /* Apply clipping after so we never project past the clip plane T25423. */
+ transform_convert_clip_mirror_modifier_apply(tc);
+
+ /* Normal updating. */
BKE_curve_dimension_update(cu);
}
}
diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 45df0e66691..4932a5f8d23 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -78,14 +78,12 @@ static short get_bezt_sel_triple_flag(BezTriple *bezt, const bool handles_visibl
flag = ((bezt->f1 & SELECT) ? SEL_F1 : 0) | ((bezt->f2 & SELECT) ? SEL_F2 : 0) |
((bezt->f3 & SELECT) ? SEL_F3 : 0);
}
- else {
- if (bezt->f2 & SELECT) {
- flag = SEL_ALL;
- }
+ else if (bezt->f2 & SELECT) {
+ flag = SEL_ALL;
}
/* Special case for auto & aligned handles */
- if (flag != SEL_ALL && flag & SEL_F2) {
+ if ((flag != SEL_ALL) && (flag & SEL_F2)) {
if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
flag = SEL_ALL;
}
@@ -316,7 +314,7 @@ static void createTransGPencil_curves(bContext *C,
}
}
else if (handles_visible) {
- if (BEZT_ISSEL_IDX(bezt, j)) {
+ if (sel) {
td->flag = TD_SELECTED;
}
else {
diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c
index 20ac7dcb998..fbfce41d555 100644
--- a/source/blender/editors/transform/transform_convert_lattice.c
+++ b/source/blender/editors/transform/transform_convert_lattice.c
@@ -122,7 +122,7 @@ void recalcData_lattice(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Lattice *la = tc->obedit->data;
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
if (la->editlatt->latt->flag & LT_OUTSIDE) {
outside_lattice(la->editlatt->latt);
}
diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c
index 6f5c0318054..f38f3ccf421 100644
--- a/source/blender/editors/transform/transform_convert_mball.c
+++ b/source/blender/editors/transform/transform_convert_mball.c
@@ -30,6 +30,8 @@
#include "BKE_context.h"
#include "transform.h"
+#include "transform_snap.h"
+
#include "transform_convert.h"
/* -------------------------------------------------------------------- */
@@ -128,3 +130,21 @@ void createTransMBallVerts(TransInfo *t)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Recalc Meta Ball
+ * \{ */
+
+void recalcData_mball(TransInfo *t)
+{
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ if (tc->data_len) {
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 93c36645873..f715228e25e 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -48,7 +48,575 @@
#include "transform_convert.h"
+/* -------------------------------------------------------------------- */
+/** \name Container TransCustomData Creation
+ * \{ */
+
+struct TransCustomDataMergeGroup {
+ /** map {BMVert: TransCustomDataLayerVert} */
+ struct LinkNode **cd_loop_groups;
+};
+
+struct TransCustomDataLayer {
+ BMesh *bm;
+ struct MemArena *arena;
+
+ struct GHash *origfaces;
+ struct BMesh *bm_origfaces;
+
+ /* Special handle for multi-resolution. */
+ int cd_loop_mdisp_offset;
+
+ /* Optionally merge custom-data groups (this keeps UVs connected for example). */
+ struct {
+ /** map {BMVert: TransDataBasic} */
+ struct GHash *origverts;
+ struct TransCustomDataMergeGroup *data;
+ int data_len;
+ /** Array size of 'layer_math_map_len'
+ * maps #TransCustomDataLayerVert.cd_group index to absolute #CustomData layer index */
+ int *customdatalayer_map;
+ /** Number of math BMLoop layers. */
+ int customdatalayer_map_len;
+ } merge_group;
+
+ bool use_merge_group;
+};
+
+static void tc_mesh_customdatacorrect_free_fn(struct TransInfo *UNUSED(t),
+ struct TransDataContainer *UNUSED(tc),
+ struct TransCustomData *custom_data)
+{
+ struct TransCustomDataLayer *tcld = custom_data->data;
+ bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+
+ if (tcld->bm_origfaces) {
+ BM_mesh_free(tcld->bm_origfaces);
+ }
+ if (tcld->origfaces) {
+ BLI_ghash_free(tcld->origfaces, NULL, NULL);
+ }
+ if (tcld->merge_group.origverts) {
+ BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL);
+ }
+ if (tcld->arena) {
+ BLI_memarena_free(tcld->arena);
+ }
+ if (tcld->merge_group.customdatalayer_map) {
+ MEM_freeN(tcld->merge_group.customdatalayer_map);
+ }
+
+ MEM_freeN(tcld);
+ custom_data->data = NULL;
+}
+
#define USE_FACE_SUBSTITUTE
+#ifdef USE_FACE_SUBSTITUTE
+# define FACE_SUBSTITUTE_INDEX INT_MIN
+
+/**
+ * Search for a neighboring face with area and preferably without selected vertex.
+ * Used to replace area-less faces in custom-data correction.
+ */
+static BMFace *tc_mesh_customdatacorrect_find_best_face_substitute(BMFace *f)
+{
+ BMFace *best_face = NULL;
+ BMLoop *l;
+ BMIter liter;
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BMLoop *l_radial_next = l->radial_next;
+ BMFace *f_test = l_radial_next->f;
+ if (f_test == f) {
+ continue;
+ }
+ if (is_zero_v3(f_test->no)) {
+ continue;
+ }
+
+ /* Check the loops edge isn't selected. */
+ if (!BM_elem_flag_test(l_radial_next->v, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(l_radial_next->next->v, BM_ELEM_SELECT)) {
+ /* Prefer edges with unselected vertices.
+ * Useful for extrude. */
+ best_face = f_test;
+ break;
+ }
+ if (best_face == NULL) {
+ best_face = f_test;
+ }
+ }
+ return best_face;
+}
+
+static void tc_mesh_customdatacorrect_face_substitute_set(struct TransCustomDataLayer *tcld,
+ BMFace *f,
+ BMFace *f_copy)
+{
+ BLI_assert(is_zero_v3(f->no));
+ BMesh *bm = tcld->bm;
+ /* It is impossible to calculate the loops weights of a face without area.
+ * Find a substitute. */
+ BMFace *f_substitute = tc_mesh_customdatacorrect_find_best_face_substitute(f);
+ if (f_substitute) {
+ /* Copy the custom-data from the substitute face. */
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_loop_interp_from_face(bm, l_iter, f_substitute, false, false);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* Use the substitute face as the reference during the transformation. */
+ BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true);
+
+ /* Hack: reference substitute face in `f_copy->no`.
+ * `tcld->origfaces` is already used to restore the initial value. */
+ BM_elem_index_set(f_copy, FACE_SUBSTITUTE_INDEX);
+ *((BMFace **)&f_copy->no[0]) = f_substitute_copy;
+ }
+}
+
+static BMFace *tc_mesh_customdatacorrect_face_substitute_get(BMFace *f_copy)
+{
+ BLI_assert(BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX);
+ return *((BMFace **)&f_copy->no[0]);
+}
+
+#endif /* USE_FACE_SUBSTITUTE */
+
+static void tc_mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld,
+ struct TransDataBasic *td,
+ const int index)
+{
+ BMesh *bm = tcld->bm;
+ BMVert *v = td->extra;
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
+ l_num = liter.count;
+ loop_weights = tcld->use_merge_group ? BLI_array_alloca(loop_weights, l_num) : NULL;
+ for (j = 0; j < l_num; j++) {
+ BMLoop *l = BM_iter_step(&liter);
+ BMLoop *l_prev, *l_next;
+
+ /* Generic custom-data correction. Copy face data. */
+ void **val_p;
+ if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) {
+ BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true);
+ *val_p = f_copy;
+#ifdef USE_FACE_SUBSTITUTE
+ if (is_zero_v3(l->f->no)) {
+ tc_mesh_customdatacorrect_face_substitute_set(tcld, l->f, f_copy);
+ }
+#endif
+ }
+
+ if (tcld->use_merge_group) {
+ if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
+ (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) {
+ loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ }
+
+ if (tcld->use_merge_group) {
+ /* Store cd_loop_groups. */
+ struct TransCustomDataMergeGroup *merge_data = &tcld->merge_group.data[index];
+ if (l_num != 0) {
+ merge_data->cd_loop_groups = BLI_memarena_alloc(
+ tcld->arena, tcld->merge_group.customdatalayer_map_len * sizeof(void *));
+ for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
+ const int layer_nr = tcld->merge_group.customdatalayer_map[j];
+ merge_data->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(
+ bm, v, layer_nr, loop_weights, tcld->arena);
+ }
+ }
+ else {
+ merge_data->cd_loop_groups = NULL;
+ }
+
+ BLI_ghash_insert(tcld->merge_group.origverts, v, td);
+ }
+}
+
+static void tc_mesh_customdatacorrect_init_container_generic(TransDataContainer *UNUSED(tc),
+ struct TransCustomDataLayer *tcld)
+{
+ BMesh *bm = tcld->bm;
+
+ 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 loop custom-data. */
+ BM_mesh_copy_init_customdata_all_layers(bm_origfaces, bm, BM_LOOP, NULL);
+
+ tcld->origfaces = origfaces;
+ tcld->bm_origfaces = bm_origfaces;
+
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ tcld->cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+}
+
+static void tc_mesh_customdatacorrect_init_container_merge_group(TransDataContainer *tc,
+ struct TransCustomDataLayer *tcld)
+{
+ BMesh *bm = tcld->bm;
+ BLI_assert(CustomData_has_math(&bm->ldata));
+
+ /* TODO: We don't need `layer_math_map` when there are no loops linked
+ * to one of the sliding vertices. */
+
+ /* Over allocate, only 'math' layers are indexed. */
+ int *customdatalayer_map = MEM_mallocN(sizeof(int) * bm->ldata.totlayer, __func__);
+ int layer_math_map_len = 0;
+ for (int i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ customdatalayer_map[layer_math_map_len++] = i;
+ }
+ }
+ BLI_assert(layer_math_map_len != 0);
+
+ tcld->merge_group.data_len = tc->data_len + tc->data_mirror_len;
+ tcld->merge_group.customdatalayer_map = customdatalayer_map;
+ tcld->merge_group.customdatalayer_map_len = layer_math_map_len;
+ tcld->merge_group.origverts = BLI_ghash_ptr_new_ex(__func__, tcld->merge_group.data_len);
+ tcld->merge_group.data = BLI_memarena_alloc(
+ tcld->arena, tcld->merge_group.data_len * sizeof(*tcld->merge_group.data));
+}
+
+static struct TransCustomDataLayer *tc_mesh_customdatacorrect_create(TransDataContainer *tc,
+ const bool use_merge_group)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ 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 custom-data projection. */
+ return NULL;
+ }
+ if (!CustomData_has_math(&bm->ldata) && !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ /* There is no custom-data to correct. */
+ return NULL;
+ }
+
+ struct TransCustomDataLayer *tcld = MEM_callocN(sizeof(*tcld), __func__);
+ tcld->bm = bm;
+ tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ /* Init `cd_loop_mdisp_offset` to -1 to avoid problems with a valid index. */
+ tcld->cd_loop_mdisp_offset = -1;
+ tcld->use_merge_group = use_merge_group;
+
+ tc_mesh_customdatacorrect_init_container_generic(tc, tcld);
+
+ if (tcld->use_merge_group) {
+ tc_mesh_customdatacorrect_init_container_merge_group(tc, tcld);
+ }
+
+ {
+ /* Setup Verts. */
+ int i = 0;
+
+ TransData *tob = tc->data;
+ for (int j = tc->data_len; j--; tob++, i++) {
+ tc_mesh_customdatacorrect_init_vert(tcld, (TransDataBasic *)tob, i);
+ }
+
+ TransDataMirror *td_mirror = tc->data_mirror;
+ for (int j = tc->data_mirror_len; j--; td_mirror++, i++) {
+ tc_mesh_customdatacorrect_init_vert(tcld, (TransDataBasic *)td_mirror, i);
+ }
+ }
+
+ return tcld;
+}
+
+static void tc_mesh_customdata_create(TransDataContainer *tc, const bool use_merge_group)
+{
+ struct TransCustomDataLayer *customdatacorrect;
+ customdatacorrect = tc_mesh_customdatacorrect_create(tc, use_merge_group);
+
+ if (!customdatacorrect) {
+ return;
+ }
+
+ BLI_assert(tc->custom.type.data == NULL);
+ tc->custom.type.data = customdatacorrect;
+ tc->custom.type.free_cb = tc_mesh_customdatacorrect_free_fn;
+}
+
+void transform_convert_mesh_customdatacorrect_init(TransInfo *t)
+{
+ bool use_merge_group = false;
+ if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE)) {
+ /* No custom-data correction. */
+ return;
+ }
+ use_merge_group = true;
+ }
+ else if (ELEM(t->mode,
+ TFM_TRANSLATION,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TOSPHERE,
+ TFM_SHEAR,
+ TFM_BEND,
+ TFM_SHRINKFATTEN,
+ TFM_TRACKBALL,
+ TFM_PUSHPULL,
+ TFM_ALIGN)) {
+ {
+ if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ /* No custom-data correction. */
+ return;
+ }
+ use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0;
+ }
+ }
+ else {
+ return;
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ if (tc->custom.type.data != NULL) {
+ tc_mesh_customdatacorrect_free_fn(t, tc, &tc->custom.type);
+ }
+
+ tc_mesh_customdata_create(tc, use_merge_group);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name CustomData Layer Correction Apply
+ * \{ */
+
+/**
+ * If we're sliding the vert, return its original location, if not, the current location is good.
+ */
+static const float *tc_mesh_vert_orig_co_get(struct TransCustomDataLayer *tcld, BMVert *v)
+{
+ TransDataBasic *td = BLI_ghash_lookup(tcld->merge_group.origverts, v);
+ return td ? td->iloc : v->co;
+}
+
+static void tc_mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld,
+ struct TransDataBasic *td,
+ struct TransCustomDataMergeGroup *merge_data,
+ bool do_loop_mdisps)
+{
+ BMesh *bm = tcld->bm;
+ BMVert *v = td->extra;
+ const float *co_orig_3d = td->iloc;
+
+ 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 = is_moved && tcld->merge_group.customdatalayer_map_len;
+ 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) {
+ project_plane_normalized_v3_v3v3(v_proj[1], co_orig_3d, v_proj_axis);
+ }
+
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT)
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
+ l_num = liter.count;
+ loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
+ for (j = 0; j < l_num; j++) {
+ BMFace *f_copy; /* the copy of 'f' */
+ BMLoop *l = BM_iter_step(&liter);
+
+ f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
+
+#ifdef USE_FACE_SUBSTITUTE
+ /* In some faces it is not possible to calculate interpolation,
+ * so we use a substitute. */
+ if (BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX) {
+ f_copy = tc_mesh_customdatacorrect_face_substitute_get(f_copy);
+ }
+#endif
+
+ /* only loop data, no vertex data since that contains shape keys,
+ * and we do not want to mess up other shape keys */
+ BM_loop_interp_from_face(bm, l, f_copy, false, false);
+
+ /* weight the loop */
+ if (do_loop_weight) {
+ const float eps = 1.0e-8f;
+ const BMLoop *l_prev = l->prev;
+ const BMLoop *l_next = l->next;
+ const float *co_prev = tc_mesh_vert_orig_co_get(tcld, l_prev->v);
+ const float *co_next = tc_mesh_vert_orig_co_get(tcld, l_next->v);
+ bool co_prev_ok;
+ bool co_next_ok;
+
+ /* In the unlikely case that we're next to a zero length edge -
+ * walk around the to the next.
+ *
+ * Since we only need to check if the vertex is in this corner,
+ * its not important _which_ loop - as long as its not overlapping
+ * 'sv->co_orig_3d', see: T45096. */
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
+ ((l_prev = l_prev->prev) != l->next))) {
+ co_prev = tc_mesh_vert_orig_co_get(tcld, l_prev->v);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ }
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
+ ((l_next = l_next->next) != l->prev))) {
+ co_next = tc_mesh_vert_orig_co_get(tcld, l_next->v);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ }
+
+ if (co_prev_ok && co_next_ok) {
+ const float dist = dist_signed_squared_to_corner_v3v3v3(
+ v->co, UNPACK3(v_proj), v_proj_axis);
+
+ loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ if (UNLIKELY(!isfinite(loop_weights[j]))) {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ }
+
+ if (tcld->use_merge_group) {
+ struct LinkNode **cd_loop_groups = merge_data->cd_loop_groups;
+ if (tcld->merge_group.customdatalayer_map_len && cd_loop_groups) {
+ if (do_loop_weight) {
+ for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
+ BM_vert_loop_groups_data_layer_merge_weights(
+ bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j], loop_weights);
+ }
+ }
+ else {
+ for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
+ BM_vert_loop_groups_data_layer_merge(
+ bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j]);
+ }
+ }
+ }
+ }
+
+ /* Special handling for multires
+ *
+ * Interpolate from every other loop (not ideal)
+ * However values will only be taken from loops which overlap other mdisps.
+ */
+ const bool update_loop_mdisps = is_moved && do_loop_mdisps && (tcld->cd_loop_mdisp_offset != -1);
+ if (update_loop_mdisps) {
+ float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
+ BMLoop *l;
+
+ BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
+ BM_face_calc_center_median(l->f, faces_center[j]);
+ }
+
+ BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
+ BMFace *f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
+ float f_copy_center[3];
+ BMIter liter_other;
+ BMLoop *l_other;
+ int j_other;
+
+ BM_face_calc_center_median(f_copy, f_copy_center);
+
+ BM_ITER_ELEM_INDEX (l_other, &liter_other, v, BM_LOOPS_OF_VERT, j_other) {
+ BM_face_interp_multires_ex(bm,
+ l_other->f,
+ f_copy,
+ faces_center[j_other],
+ f_copy_center,
+ tcld->cd_loop_mdisp_offset);
+ }
+ }
+ }
+}
+
+static void tc_mesh_customdatacorrect_apply(TransDataContainer *tc, bool is_final)
+{
+ if (!tc->custom.type.data) {
+ return;
+ }
+ struct TransCustomDataLayer *tcld = tc->custom.type.data;
+ const bool use_merge_group = tcld->use_merge_group;
+
+ struct TransCustomDataMergeGroup *merge_data = tcld->merge_group.data;
+ TransData *tob = tc->data;
+ for (int i = tc->data_len; i--; tob++) {
+ tc_mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)tob, merge_data, is_final);
+
+ if (use_merge_group) {
+ merge_data++;
+ }
+ }
+
+ TransDataMirror *td_mirror = tc->data_mirror;
+ for (int i = tc->data_mirror_len; i--; td_mirror++) {
+ tc_mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)td_mirror, merge_data, is_final);
+
+ if (use_merge_group) {
+ merge_data++;
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name CustomData Layer Correction Restore
+ * \{ */
+
+static void tc_mesh_customdatacorrect_restore(struct TransInfo *t)
+{
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ struct TransCustomDataLayer *tcld = tc->custom.type.data;
+ if (!tcld) {
+ continue;
+ }
+
+ BMesh *bm = tcld->bm;
+ BMesh *bm_copy = tcld->bm_origfaces;
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, tcld->origfaces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ BMFace *f_copy = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_assert(f->len == f_copy->len);
+
+ BMLoop *l_iter, *l_first, *l_copy;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ l_copy = BM_FACE_FIRST_LOOP(f_copy);
+ do {
+ /* TODO: Restore only the elements that transform. */
+ BM_elem_attrs_copy(bm_copy, bm, l_copy, l_iter);
+ l_copy = l_copy->next;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/** \name Island Creation
@@ -384,6 +952,14 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
BMEdge *e;
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+
+ /* Always clear to satisfy the assert, also predictable to leave in cleared state. */
+ BM_elem_flag_disable(e, tag_queued);
+
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+
BMVert *v1 = e->v1;
BMVert *v2 = e->v2;
int i1 = BM_elem_index_get(v1);
@@ -392,7 +968,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) {
BLI_LINKSTACK_PUSH(queue, e);
}
- BM_elem_flag_disable(e, tag_queued);
BM_elem_flag_set(e, tag_loose, bmesh_test_loose_edge(e));
}
}
@@ -420,6 +995,7 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
BMIter eiter;
BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) {
if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
+ !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN) &&
(BM_elem_flag_test(e, tag_loose) || BM_elem_flag_test(e_other, tag_loose))) {
BM_elem_flag_enable(e_other, tag_queued);
BLI_LINKSTACK_PUSH(queue_next, e_other);
@@ -433,6 +1009,11 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
BMLoop *l;
BMIter liter;
BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ if (BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ /* Don't check hidden edges or vertices in this loop
+ * since any hidden edge causes the face to be hidden too. */
for (BMLoop *l_other = l->next->next; l_other != l; l_other = l_other->next) {
BMVert *v_other = l_other->v;
BLI_assert(!ELEM(v_other, v1, v2));
@@ -445,6 +1026,7 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
BMIter eiter;
BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) {
if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
+ !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN) &&
(BM_elem_flag_test(e_other, tag_loose) ||
dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) {
BM_elem_flag_enable(e_other, tag_queued);
@@ -727,10 +1309,10 @@ void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_cr
/** \name Edit Mesh Verts Transform Creation
* \{ */
-static void transdata_center_get(const struct TransIslandData *island_data,
- const int island_index,
- const float iloc[3],
- float r_center[3])
+static void tc_mesh_transdata_center_copy(const struct TransIslandData *island_data,
+ const int island_index,
+ const float iloc[3],
+ float r_center[3])
{
if (island_data->center && island_index != -1) {
copy_v3_v3(r_center, island_data->center[island_index]);
@@ -769,7 +1351,7 @@ static void VertsToTransData(TransInfo *t,
no = eve->no;
}
- transdata_center_get(island_data, island_index, td->iloc, td->center);
+ tc_mesh_transdata_center_copy(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]);
@@ -959,7 +1541,8 @@ void createTransEditVerts(TransInfo *t)
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);
+ tc_mesh_transdata_center_copy(
+ &island_data, island_index, td_mirror->iloc, td_mirror->center);
td_mirror++;
}
@@ -1031,590 +1614,39 @@ void createTransEditVerts(TransInfo *t)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name CustomData Layer Correction
+/** \name Recalc Mesh Data
* \{ */
-struct TransCustomDataMergeGroup {
- /** map {BMVert: TransCustomDataLayerVert} */
- struct LinkNode **cd_loop_groups;
-};
-
-struct TransCustomDataLayer {
- BMesh *bm;
- struct MemArena *arena;
-
- struct GHash *origfaces;
- struct BMesh *bm_origfaces;
-
- /* Special handle for multi-resolution. */
- int cd_loop_mdisp_offset;
-
- /* Optionally merge custom-data groups (this keeps UVs connected for example). */
- struct {
- /** map {BMVert: TransDataBasic} */
- struct GHash *origverts;
- struct TransCustomDataMergeGroup *data;
- int data_len;
- /** Array size of 'layer_math_map_len'
- * maps #TransCustomDataLayerVert.cd_group index to absolute #CustomData layer index */
- int *customdatalayer_map;
- /** Number of math BMLoop layers. */
- int customdatalayer_map_len;
- } merge_group;
-
- bool use_merge_group;
-};
-
-static void mesh_customdatacorrect_free_cb(struct TransInfo *UNUSED(t),
- struct TransDataContainer *UNUSED(tc),
- struct TransCustomData *custom_data)
-{
- struct TransCustomDataLayer *tcld = custom_data->data;
- bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
-
- if (tcld->bm_origfaces) {
- BM_mesh_free(tcld->bm_origfaces);
- }
- if (tcld->origfaces) {
- BLI_ghash_free(tcld->origfaces, NULL, NULL);
- }
- if (tcld->merge_group.origverts) {
- BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL);
- }
- if (tcld->arena) {
- BLI_memarena_free(tcld->arena);
- }
- if (tcld->merge_group.customdatalayer_map) {
- MEM_freeN(tcld->merge_group.customdatalayer_map);
- }
-
- MEM_freeN(tcld);
- custom_data->data = NULL;
-}
-
-#ifdef USE_FACE_SUBSTITUTE
-
-# define FACE_SUBSTITUTE_INDEX INT_MIN
-
-/**
- * Search for a neighboring face with area and preferably without selected vertex.
- * Used to replace area-less faces in custom-data correction.
- */
-static BMFace *mesh_customdatacorrect_find_best_face_substitute(BMFace *f)
-{
- BMFace *best_face = NULL;
- BMLoop *l;
- BMIter liter;
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BMLoop *l_radial_next = l->radial_next;
- BMFace *f_test = l_radial_next->f;
- if (f_test == f) {
- continue;
- }
- if (is_zero_v3(f_test->no)) {
- continue;
- }
-
- /* Check the loops edge isn't selected. */
- if (!BM_elem_flag_test(l_radial_next->v, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(l_radial_next->next->v, BM_ELEM_SELECT)) {
- /* Prefer edges with unselected vertices.
- * Useful for extrude. */
- best_face = f_test;
- break;
- }
- if (best_face == NULL) {
- best_face = f_test;
- }
- }
- return best_face;
-}
-
-static void mesh_customdatacorrect_face_substitute_set(struct TransCustomDataLayer *tcld,
- BMFace *f,
- BMFace *f_copy)
-{
- BLI_assert(is_zero_v3(f->no));
- BMesh *bm = tcld->bm;
- /* It is impossible to calculate the loops weights of a face without area.
- * Find a substitute. */
- BMFace *f_substitute = mesh_customdatacorrect_find_best_face_substitute(f);
- if (f_substitute) {
- /* Copy the custom-data from the substitute face. */
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_loop_interp_from_face(bm, l_iter, f_substitute, false, false);
- } while ((l_iter = l_iter->next) != l_first);
-
- /* Use the substitute face as the reference during the transformation. */
- BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true);
-
- /* Hack: reference substitute face in `f_copy->no`.
- * `tcld->origfaces` is already used to restore the initial value. */
- BM_elem_index_set(f_copy, FACE_SUBSTITUTE_INDEX);
- *((BMFace **)&f_copy->no[0]) = f_substitute_copy;
- }
-}
-
-static BMFace *mesh_customdatacorrect_face_substitute_get(BMFace *f_copy)
-{
- BLI_assert(BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX);
- return *((BMFace **)&f_copy->no[0]);
-}
-
-#endif /* USE_FACE_SUBSTITUTE */
-
-static void mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld,
- struct TransDataBasic *td,
- const int index)
-{
- BMesh *bm = tcld->bm;
- BMVert *v = td->extra;
- BMIter liter;
- int j, l_num;
- float *loop_weights;
-
- // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
- BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
- l_num = liter.count;
- loop_weights = tcld->use_merge_group ? BLI_array_alloca(loop_weights, l_num) : NULL;
- for (j = 0; j < l_num; j++) {
- BMLoop *l = BM_iter_step(&liter);
- BMLoop *l_prev, *l_next;
-
- /* Generic custom-data correction. Copy face data. */
- void **val_p;
- if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) {
- BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true);
- *val_p = f_copy;
-#ifdef USE_FACE_SUBSTITUTE
- if (is_zero_v3(l->f->no)) {
- mesh_customdatacorrect_face_substitute_set(tcld, l->f, f_copy);
- }
-#endif
- }
-
- if (tcld->use_merge_group) {
- if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
- (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) {
- loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
- }
- else {
- loop_weights[j] = 0.0f;
- }
- }
- }
-
- if (tcld->use_merge_group) {
- /* Store cd_loop_groups. */
- struct TransCustomDataMergeGroup *merge_data = &tcld->merge_group.data[index];
- if (l_num != 0) {
- merge_data->cd_loop_groups = BLI_memarena_alloc(
- tcld->arena, tcld->merge_group.customdatalayer_map_len * sizeof(void *));
- for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
- const int layer_nr = tcld->merge_group.customdatalayer_map[j];
- merge_data->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(
- bm, v, layer_nr, loop_weights, tcld->arena);
- }
- }
- else {
- merge_data->cd_loop_groups = NULL;
- }
-
- BLI_ghash_insert(tcld->merge_group.origverts, v, td);
- }
-}
-
-static void mesh_customdatacorrect_init_container_generic(TransDataContainer *UNUSED(tc),
- struct TransCustomDataLayer *tcld)
-{
- BMesh *bm = tcld->bm;
-
- 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 loop custom-data. */
- BM_mesh_copy_init_customdata_all_layers(bm_origfaces, bm, BM_LOOP, NULL);
-
- tcld->origfaces = origfaces;
- tcld->bm_origfaces = bm_origfaces;
-
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- tcld->cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
-}
-
-static void mesh_customdatacorrect_init_container_merge_group(TransDataContainer *tc,
- struct TransCustomDataLayer *tcld)
-{
- BMesh *bm = tcld->bm;
- BLI_assert(CustomData_has_math(&bm->ldata));
-
- /* TODO: We don't need `layer_math_map` when there are no loops linked
- * to one of the sliding vertices. */
-
- /* Over allocate, only 'math' layers are indexed. */
- int *customdatalayer_map = MEM_mallocN(sizeof(int) * bm->ldata.totlayer, __func__);
- int layer_math_map_len = 0;
- for (int i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- customdatalayer_map[layer_math_map_len++] = i;
- }
- }
- BLI_assert(layer_math_map_len != 0);
-
- tcld->merge_group.data_len = tc->data_len + tc->data_mirror_len;
- tcld->merge_group.customdatalayer_map = customdatalayer_map;
- tcld->merge_group.customdatalayer_map_len = layer_math_map_len;
- tcld->merge_group.origverts = BLI_ghash_ptr_new_ex(__func__, tcld->merge_group.data_len);
- tcld->merge_group.data = BLI_memarena_alloc(
- tcld->arena, tcld->merge_group.data_len * sizeof(*tcld->merge_group.data));
-}
-
-static void mesh_customdatacorrect_init_container(TransDataContainer *tc,
- const bool use_merge_group)
-{
- if (tc->custom.type.data) {
- /* The custom-data correction has been initiated before.
- * Free since some modes have different settings. */
- mesh_customdatacorrect_free_cb(NULL, tc, &tc->custom.type);
- }
-
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- 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 custom-data projection. */
- return;
- }
- if (!CustomData_has_math(&bm->ldata) && !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
- /* There is no custom-data to correct. */
- return;
- }
-
- struct TransCustomDataLayer *tcld = MEM_callocN(sizeof(*tcld), __func__);
- tcld->bm = bm;
- tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- /* Init `cd_loop_mdisp_offset` to -1 to avoid problems with a valid index. */
- tcld->cd_loop_mdisp_offset = -1;
- tcld->use_merge_group = use_merge_group;
-
- mesh_customdatacorrect_init_container_generic(tc, tcld);
-
- if (tcld->use_merge_group) {
- mesh_customdatacorrect_init_container_merge_group(tc, tcld);
- }
-
- {
- /* Setup Verts. */
- int i = 0;
-
- TransData *tob = tc->data;
- for (int j = tc->data_len; j--; tob++, i++) {
- mesh_customdatacorrect_init_vert(tcld, (TransDataBasic *)tob, i);
- }
-
- TransDataMirror *td_mirror = tc->data_mirror;
- for (int j = tc->data_mirror_len; j--; td_mirror++, i++) {
- mesh_customdatacorrect_init_vert(tcld, (TransDataBasic *)td_mirror, i);
- }
- }
-
- tc->custom.type.data = tcld;
- tc->custom.type.free_cb = mesh_customdatacorrect_free_cb;
-}
-
-void mesh_customdatacorrect_init(TransInfo *t)
-{
- bool use_merge_group = false;
- if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE)) {
- /* No custom-data correction. */
- return;
- }
- use_merge_group = true;
- }
- else if (ELEM(t->mode,
- TFM_TRANSLATION,
- TFM_ROTATION,
- TFM_RESIZE,
- TFM_TOSPHERE,
- TFM_SHEAR,
- TFM_BEND,
- TFM_SHRINKFATTEN,
- TFM_TRACKBALL,
- TFM_PUSHPULL,
- TFM_ALIGN)) {
- {
- if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
- /* No custom-data correction. */
- return;
- }
- use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0;
- }
- }
- else {
- return;
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- mesh_customdatacorrect_init_container(tc, use_merge_group);
- }
-}
-
-/**
- * If we're sliding the vert, return its original location, if not, the current location is good.
- */
-static const float *trans_vert_orig_co_get(struct TransCustomDataLayer *tcld, BMVert *v)
-{
- TransDataBasic *td = BLI_ghash_lookup(tcld->merge_group.origverts, v);
- return td ? td->iloc : v->co;
-}
-
-static void mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld,
- struct TransDataBasic *td,
- struct TransCustomDataMergeGroup *merge_data,
- bool do_loop_mdisps)
+static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc)
{
- BMesh *bm = tcld->bm;
- BMVert *v = td->extra;
- const float *co_orig_3d = td->iloc;
-
- 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 = is_moved && tcld->merge_group.customdatalayer_map_len;
- 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) {
- project_plane_normalized_v3_v3v3(v_proj[1], co_orig_3d, v_proj_axis);
- }
-
- // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT)
- BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
- l_num = liter.count;
- loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
- for (j = 0; j < l_num; j++) {
- BMFace *f_copy; /* the copy of 'f' */
- BMLoop *l = BM_iter_step(&liter);
-
- f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
-
-#ifdef USE_FACE_SUBSTITUTE
- /* In some faces it is not possible to calculate interpolation,
- * so we use a substitute. */
- if (BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX) {
- f_copy = mesh_customdatacorrect_face_substitute_get(f_copy);
- }
-#endif
-
- /* only loop data, no vertex data since that contains shape keys,
- * and we do not want to mess up other shape keys */
- BM_loop_interp_from_face(bm, l, f_copy, false, false);
-
- /* weight the loop */
- if (do_loop_weight) {
- const float eps = 1.0e-8f;
- const BMLoop *l_prev = l->prev;
- const BMLoop *l_next = l->next;
- const float *co_prev = trans_vert_orig_co_get(tcld, l_prev->v);
- const float *co_next = trans_vert_orig_co_get(tcld, l_next->v);
- bool co_prev_ok;
- bool co_next_ok;
-
- /* In the unlikely case that we're next to a zero length edge -
- * walk around the to the next.
- *
- * Since we only need to check if the vertex is in this corner,
- * its not important _which_ loop - as long as its not overlapping
- * 'sv->co_orig_3d', see: T45096. */
- project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
- while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
- ((l_prev = l_prev->prev) != l->next))) {
- co_prev = trans_vert_orig_co_get(tcld, l_prev->v);
- project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
- }
- project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
- while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
- ((l_next = l_next->next) != l->prev))) {
- co_next = trans_vert_orig_co_get(tcld, l_next->v);
- project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
- }
-
- if (co_prev_ok && co_next_ok) {
- const float dist = dist_signed_squared_to_corner_v3v3v3(
- v->co, UNPACK3(v_proj), v_proj_axis);
-
- loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
- if (UNLIKELY(!isfinite(loop_weights[j]))) {
- loop_weights[j] = 0.0f;
+ if (tc->use_mirror_axis_any) {
+ int i;
+ TransData *td;
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ if (td->flag & (TD_MIRROR_EDGE_X | TD_MIRROR_EDGE_Y | TD_MIRROR_EDGE_Z)) {
+ if (td->flag & TD_MIRROR_EDGE_X) {
+ td->loc[0] = 0.0f;
}
- }
- else {
- loop_weights[j] = 0.0f;
- }
- }
- }
-
- if (tcld->use_merge_group) {
- struct LinkNode **cd_loop_groups = merge_data->cd_loop_groups;
- if (tcld->merge_group.customdatalayer_map_len && cd_loop_groups) {
- if (do_loop_weight) {
- for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
- BM_vert_loop_groups_data_layer_merge_weights(
- bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j], loop_weights);
+ if (td->flag & TD_MIRROR_EDGE_Y) {
+ td->loc[1] = 0.0f;
}
- }
- else {
- for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
- BM_vert_loop_groups_data_layer_merge(
- bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j]);
+ if (td->flag & TD_MIRROR_EDGE_Z) {
+ td->loc[2] = 0.0f;
}
}
}
- }
-
- /* Special handling for multires
- *
- * Interpolate from every other loop (not ideal)
- * However values will only be taken from loops which overlap other mdisps.
- */
- const bool update_loop_mdisps = is_moved && do_loop_mdisps && (tcld->cd_loop_mdisp_offset != -1);
- if (update_loop_mdisps) {
- float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
- BMLoop *l;
-
- BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
- BM_face_calc_center_median(l->f, faces_center[j]);
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
- BMFace *f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
- float f_copy_center[3];
- BMIter liter_other;
- BMLoop *l_other;
- int j_other;
-
- BM_face_calc_center_median(f_copy, f_copy_center);
-
- BM_ITER_ELEM_INDEX (l_other, &liter_other, v, BM_LOOPS_OF_VERT, j_other) {
- BM_face_interp_multires_ex(bm,
- l_other->f,
- f_copy,
- faces_center[j_other],
- f_copy_center,
- tcld->cd_loop_mdisp_offset);
- }
- }
- }
-}
-
-static void mesh_customdatacorrect_apply(TransInfo *t, bool is_final)
-{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (!tc->custom.type.data) {
- continue;
- }
- struct TransCustomDataLayer *tcld = tc->custom.type.data;
- const bool use_merge_group = tcld->use_merge_group;
-
- struct TransCustomDataMergeGroup *merge_data = tcld->merge_group.data;
- TransData *tob = tc->data;
- for (int i = tc->data_len; i--; tob++) {
- mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)tob, merge_data, is_final);
-
- if (use_merge_group) {
- merge_data++;
- }
- }
TransDataMirror *td_mirror = tc->data_mirror;
- for (int i = tc->data_mirror_len; i--; td_mirror++) {
- mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)td_mirror, merge_data, is_final);
-
- if (use_merge_group) {
- merge_data++;
+ for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
+ copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
+ if (td_mirror->flag & TD_MIRROR_X) {
+ td_mirror->loc[0] *= -1;
}
- }
- }
-}
-
-static void mesh_customdatacorrect_restore(struct TransInfo *t)
-{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- struct TransCustomDataLayer *tcld = tc->custom.type.data;
- if (!tcld) {
- continue;
- }
-
- BMesh *bm = tcld->bm;
- BMesh *bm_copy = tcld->bm_origfaces;
-
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, tcld->origfaces) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- BMFace *f_copy = BLI_ghashIterator_getValue(&gh_iter);
- BLI_assert(f->len == f_copy->len);
-
- BMLoop *l_iter, *l_first, *l_copy;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- l_copy = BM_FACE_FIRST_LOOP(f_copy);
- do {
- /* TODO: Restore only the elements that transform. */
- BM_elem_attrs_copy(bm_copy, bm, l_copy, l_iter);
- l_copy = l_copy->next;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Recalc Mesh Data
- * \{ */
-
-static void mesh_apply_to_mirror(TransInfo *t)
-{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->use_mirror_axis_any) {
- int i;
- TransData *td;
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->flag & (TD_MIRROR_EDGE_X | TD_MIRROR_EDGE_Y | TD_MIRROR_EDGE_Z)) {
- if (td->flag & TD_MIRROR_EDGE_X) {
- td->loc[0] = 0.0f;
- }
- if (td->flag & TD_MIRROR_EDGE_Y) {
- td->loc[1] = 0.0f;
- }
- if (td->flag & TD_MIRROR_EDGE_Z) {
- td->loc[2] = 0.0f;
- }
- }
+ if (td_mirror->flag & TD_MIRROR_Y) {
+ td_mirror->loc[1] *= -1;
}
-
- TransDataMirror *td_mirror = tc->data_mirror;
- for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
- copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
- if (td_mirror->flag & TD_MIRROR_X) {
- td_mirror->loc[0] *= -1;
- }
- if (td_mirror->flag & TD_MIRROR_Y) {
- td_mirror->loc[1] *= -1;
- }
- if (td_mirror->flag & TD_MIRROR_Z) {
- td_mirror->loc[2] *= -1;
- }
+ if (td_mirror->flag & TD_MIRROR_Z) {
+ td_mirror->loc[2] *= -1;
}
}
}
@@ -1623,24 +1655,28 @@ static void mesh_apply_to_mirror(TransInfo *t)
void recalcData_mesh(TransInfo *t)
{
bool is_canceling = t->state == TRANS_CANCEL;
- /* mirror modifier clipping? */
+ /* Apply corrections. */
if (!is_canceling) {
- /* apply clipping after so we never project past the clip plane T25423. */
applyProject(t);
- clipMirrorModifier(t);
- if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
- mesh_apply_to_mirror(t);
- }
+ bool do_mirror = !(t->flag & T_NO_MIRROR);
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ /* Apply clipping after so we never project past the clip plane T25423. */
+ transform_convert_clip_mirror_modifier_apply(tc);
+
+ if (do_mirror) {
+ tc_mesh_transdata_mirror_apply(tc);
+ }
- mesh_customdatacorrect_apply(t, false);
+ tc_mesh_customdatacorrect_apply(tc, false);
+ }
}
else {
- mesh_customdatacorrect_restore(t);
+ tc_mesh_customdatacorrect_restore(t);
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
EDBM_mesh_normals_update(em);
BKE_editmesh_looptri_calc(em);
@@ -1660,7 +1696,9 @@ void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
if (!is_canceling && ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
/* NOTE(joeedh): Handle multi-res re-projection,
* done on transform completion since it's really slow. */
- mesh_customdatacorrect_apply(t, true);
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ tc_mesh_customdatacorrect_apply(tc, true);
+ }
}
if (use_automerge) {
diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c
index 5dbb1947773..7c61da31f72 100644
--- a/source/blender/editors/transform/transform_convert_mesh_skin.c
+++ b/source/blender/editors/transform/transform_convert_mesh_skin.c
@@ -47,9 +47,9 @@
/** \name Edit Mesh #CD_MVERT_SKIN Transform Creation
* \{ */
-static float *mesh_skin_transdata_center(const struct TransIslandData *island_data,
- const int island_index,
- BMVert *eve)
+static float *tc_mesh_skin_transdata_center(const struct TransIslandData *island_data,
+ const int island_index,
+ BMVert *eve)
{
if (island_data->center && island_index != -1) {
return island_data->center[island_index];
@@ -57,11 +57,11 @@ static float *mesh_skin_transdata_center(const struct TransIslandData *island_da
return eve->co;
}
-static void mesh_skin_transdata_create(TransDataBasic *td,
- BMEditMesh *em,
- BMVert *eve,
- const struct TransIslandData *island_data,
- const int island_index)
+static void tc_mesh_skin_transdata_create(TransDataBasic *td,
+ BMEditMesh *em,
+ BMVert *eve,
+ const struct TransIslandData *island_data,
+ const int island_index)
{
BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
@@ -78,7 +78,7 @@ static void mesh_skin_transdata_create(TransDataBasic *td,
td->flag |= TD_SELECTED;
}
- copy_v3_v3(td->center, mesh_skin_transdata_center(island_data, island_index, eve));
+ copy_v3_v3(td->center, tc_mesh_skin_transdata_center(island_data, island_index, eve));
td->extra = eve;
}
@@ -209,7 +209,7 @@ void createTransMeshSkin(TransInfo *t)
}
if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
- mesh_skin_transdata_create(
+ tc_mesh_skin_transdata_create(
(TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
int elem_index = mirror_data.vert_map[a].index;
@@ -221,7 +221,7 @@ void createTransMeshSkin(TransInfo *t)
td_mirror++;
}
else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
+ tc_mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
createSpaceNormal(td->axismtx, eve->no);
@@ -275,7 +275,7 @@ void createTransMeshSkin(TransInfo *t)
/** \name Recalc Mesh Data
* \{ */
-static void mesh_skin_apply_to_mirror(TransInfo *t)
+static void tc_mesh_skin_apply_to_mirror(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (tc->use_mirror_axis_any) {
@@ -292,13 +292,13 @@ void recalcData_mesh_skin(TransInfo *t)
bool is_canceling = t->state == TRANS_CANCEL;
/* mirror modifier clipping? */
if (!is_canceling) {
- if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
- mesh_skin_apply_to_mirror(t);
+ if (!(t->flag & T_NO_MIRROR)) {
+ tc_mesh_skin_apply_to_mirror(t);
}
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
EDBM_mesh_normals_update(em);
BKE_editmesh_looptri_calc(em);
diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c
index a5f90e9ac5f..d91a2a8be4b 100644
--- a/source/blender/editors/transform/transform_convert_mesh_uv.c
+++ b/source/blender/editors/transform/transform_convert_mesh_uv.c
@@ -475,7 +475,7 @@ void recalcData_uv(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0);
+ DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 30418471d6d..34be89e5ed9 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -491,7 +491,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
}
- SEQ_sort(t->scene);
+ SEQ_sort(seqbasep);
}
else {
/* Canceled, need to update the strips display */
@@ -707,7 +707,7 @@ static void flushTransSeq(TransInfo *t)
/* originally TFM_TIME_EXTEND, transform changes */
if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
- /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
+ /* Special annoying case here, need to calc meta-strips with TFM_TIME_EXTEND only */
/* calc all meta's then effects T27953. */
for (seq = seqbasep->first; seq; seq = seq->next) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index c0c4b22da98..71c91221fbb 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -414,8 +414,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
int orient_type_set = -1;
int orient_type_matrix_set = -1;
- bool use_orient_axis = false;
-
if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
orient_type_scene = orient_slot->type;
@@ -435,7 +433,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- use_orient_axis = true;
}
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
@@ -457,28 +454,23 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (orient_type_set != -1) {
orient_type_default = orient_type_set;
+ t->is_orient_set = true;
}
else if (orient_type_matrix_set != -1) {
orient_type_default = orient_type_set = orient_type_matrix_set;
+ t->is_orient_set = true;
}
else if (t->con.mode & CON_APPLY) {
orient_type_default = orient_type_set = orient_type_scene;
}
else {
+ orient_type_default = orient_type_scene;
if (orient_type_scene == V3D_ORIENT_GLOBAL) {
orient_type_set = V3D_ORIENT_LOCAL;
}
else {
orient_type_set = V3D_ORIENT_GLOBAL;
}
-
- if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) &&
- (t->mode != TFM_ALIGN)) {
- orient_type_default = V3D_ORIENT_VIEW;
- }
- else {
- orient_type_default = orient_type_scene;
- }
}
BLI_assert(!ELEM(-1, orient_type_default, orient_type_set));
@@ -487,9 +479,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
}
- orient_types[0] = (short)orient_type_default;
- orient_types[1] = (short)orient_type_scene;
- orient_types[2] = (short)orient_type_set;
+ orient_types[O_DEFAULT] = (short)orient_type_default;
+ orient_types[O_SCENE] = (short)orient_type_scene;
+ orient_types[O_SET] = (short)orient_type_set;
for (int i = 0; i < 3; i++) {
/* For efficiency, avoid calculating the same orientation twice. */
@@ -506,9 +498,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
- /* Set orient_curr to -1 in order to force the update in
- * `transform_orientations_current_set`. */
- t->orient_curr = -1;
transform_orientations_current_set(t, (t->con.mode & CON_APPLY) ? 2 : 0);
}
@@ -538,7 +527,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else {
/* Avoid mirroring for unsupported contexts. */
- t->options |= CTX_NO_MIRROR;
+ t->flag |= T_NO_MIRROR;
}
/* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index d14f693da9c..d61e7bb867c 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -45,6 +45,7 @@
#include "transform.h"
#include "transform_convert.h"
+#include "transform_orientations.h"
#include "transform_snap.h"
/* Own include. */
@@ -1263,7 +1264,7 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
if (t->data_type == TC_MESH_VERTS) {
/* Init Custom Data correction.
* Ideally this should be called when creating the TransData. */
- mesh_customdatacorrect_init(t);
+ transform_convert_mesh_customdatacorrect_init(t);
}
/* TODO(germano): Some of these operations change the `t->mode`.
@@ -1271,4 +1272,38 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
* BLI_assert(t->mode == mode); */
}
+/**
+ * When in modal and not set, initializes a default orientation for the mode.
+ */
+void transform_mode_default_modal_orientation_set(TransInfo *t, int type)
+{
+ /* Currently only these types are supported. */
+ BLI_assert(ELEM(type, V3D_ORIENT_GLOBAL, V3D_ORIENT_VIEW));
+
+ if (t->is_orient_set) {
+ return;
+ }
+
+ if (!(t->flag & T_MODAL)) {
+ return;
+ }
+
+ if (t->orient[O_DEFAULT].type == type) {
+ return;
+ }
+
+ RegionView3D *rv3d = NULL;
+ if ((type == V3D_ORIENT_VIEW) && (t->spacetype == SPACE_VIEW3D) && t->region &&
+ (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ rv3d = t->region->regiondata;
+ }
+
+ t->orient[O_DEFAULT].type = ED_transform_calc_orientation_from_type_ex(
+ NULL, t->orient[O_DEFAULT].matrix, NULL, rv3d, NULL, NULL, type, 0);
+
+ if (t->orient_curr == O_DEFAULT) {
+ /* Update Orientation. */
+ transform_orientations_current_set(t, O_DEFAULT);
+ }
+}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index 6d7a0b528ae..106dc68c9ee 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -61,6 +61,7 @@ short getAnimEdit_SnapMode(TransInfo *t);
void doAnimEdit_SnapFrame(
TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap);
void transform_mode_init(TransInfo *t, struct wmOperator *op, const int mode);
+void transform_mode_default_modal_orientation_set(TransInfo *t, int type);
/* transform_mode_align.c */
void initAlign(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
index ee63bf4be6f..68416c780ef 100644
--- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -107,7 +107,6 @@ void initCurveShrinkFatten(TransInfo *t)
t->num.unit_sys = t->scene->unit.system;
t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
index c78115561b2..b7b3de69731 100644
--- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
+++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
@@ -148,5 +148,7 @@ void initNormalRotation(TransInfo *t)
storeCustomLNorValue(tc, bm);
}
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c
index e67c6c03481..7c496d271ef 100644
--- a/source/blender/editors/transform/transform_mode_gpopacity.c
+++ b/source/blender/editors/transform/transform_mode_gpopacity.c
@@ -117,7 +117,6 @@ void initGPOpacity(TransInfo *t)
t->num.unit_sys = t->scene->unit.system;
t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
index 95e3d89d2b7..608a49f38b1 100644
--- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
@@ -119,7 +119,6 @@ void initGPShrinkFatten(TransInfo *t)
t->num.unit_sys = t->scene->unit.system;
t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
index 3019984d70b..857ee37f0ad 100644
--- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
@@ -133,7 +133,6 @@ void initMaskShrinkFatten(TransInfo *t)
t->num.unit_sys = t->scene->unit.system;
t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c
index 9891af8b9a4..f225f1a7c06 100644
--- a/source/blender/editors/transform/transform_mode_mirror.c
+++ b/source/blender/editors/transform/transform_mode_mirror.c
@@ -235,8 +235,5 @@ void initMirror(TransInfo *t)
initMouseInputMode(t, &t->mouse, INPUT_NONE);
t->flag |= T_NULL_ONE;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
- }
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index 4d0bb7fbe9c..0d7d0be3c0e 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -176,7 +176,6 @@ void initResize(TransInfo *t)
t->num.val_flag[2] |= NUM_NULL_ONE;
t->num.flag |= NUM_AFFECT_ALL;
if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
@@ -194,5 +193,7 @@ void initResize(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->num.unit_type[1] = B_UNIT_NONE;
t->num.unit_type[2] = B_UNIT_NONE;
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_GLOBAL);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 8d8594d5775..0fdbfb25989 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -249,5 +249,7 @@ void initRotation(TransInfo *t)
if (t->flag & T_2D_EDIT) {
t->flag |= T_NO_CONSTRAINT;
}
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
index a41c49710b9..23ee55bf6c5 100644
--- a/source/blender/editors/transform/transform_mode_shear.c
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -232,5 +232,7 @@ void initShear(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
t->flag |= T_NO_CONSTRAINT;
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c
index 8beacb844b9..77e57484bef 100644
--- a/source/blender/editors/transform/transform_mode_skin_resize.c
+++ b/source/blender/editors/transform/transform_mode_skin_resize.c
@@ -111,7 +111,6 @@ void initSkinResize(TransInfo *t)
t->num.val_flag[2] |= NUM_NULL_ONE;
t->num.flag |= NUM_AFFECT_ALL;
if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 41fc6ee0aaf..175b7b52a1a 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -470,5 +470,8 @@ void initTranslation(TransInfo *t)
t->num.unit_type[1] = B_UNIT_NONE;
t->num.unit_type[2] = B_UNIT_NONE;
}
+
+ transform_mode_default_modal_orientation_set(
+ t, (t->options & CTX_CAMERA) ? V3D_ORIENT_VIEW : V3D_ORIENT_GLOBAL);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 5a5f478fc2b..d97bcba161f 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -445,7 +445,7 @@ int BIF_countTransformOrientation(const bContext *C)
return BLI_listbase_count(transform_orientations);
}
-void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
+void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char r_name[64])
{
if (r_name) {
BLI_strncpy(r_name, ts->name, MAX_NAME);
@@ -671,10 +671,6 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien
void transform_orientations_current_set(TransInfo *t, const short orient_index)
{
- if (t->orient_curr == orient_index) {
- return;
- }
-
const short orientation = t->orient[orient_index].type;
const char *spacename = transform_orientations_spacename_get(t, orientation);