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/transform.c')
-rw-r--r--source/blender/editors/transform/transform.c694
1 files changed, 420 insertions, 274 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 24499688835..061d00424b8 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -44,12 +44,14 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h" /* PET modes */
+#include "BLI_alloca.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_ghash.h"
+#include "BLI_memarena.h"
#include "BKE_nla.h"
#include "BKE_editmesh_bvh.h"
@@ -93,8 +95,8 @@
#define MAX_INFO_LEN 256
static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
-static int doEdgeSlide(TransInfo *t, float perc);
-static int doVertSlide(TransInfo *t, float perc);
+static void doEdgeSlide(TransInfo *t, float perc);
+static void doVertSlide(TransInfo *t, float perc);
static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
static void drawVertSlide(const struct bContext *C, TransInfo *t);
@@ -138,6 +140,9 @@ static void applyCurveShrinkFatten(TransInfo *t, const int mval[2]);
static void initMaskShrinkFatten(TransInfo *t);
static void applyMaskShrinkFatten(TransInfo *t, const int mval[2]);
+static void initGPShrinkFatten(TransInfo *t);
+static void applyGPShrinkFatten(TransInfo *t, const int mval[2]);
+
static void initTrackball(TransInfo *t);
static void applyTrackball(TransInfo *t, const int mval[2]);
@@ -200,6 +205,12 @@ static bool transdata_check_local_center(TransInfo *t, short around)
);
}
+bool transdata_check_local_islands(TransInfo *t, short around)
+{
+ return ((around == V3D_LOCAL) && (
+ (t->obedit && ELEM(t->obedit->type, OB_MESH))));
+}
+
/* ************************** SPACE DEPENDANT CODE **************************** */
void setTransformViewMatrices(TransInfo *t)
@@ -579,7 +590,10 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
- if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & CTX_GPENCIL_STROKES) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
WM_paint_cursor_tag_redraw(window, t->ar);
@@ -662,8 +676,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
/* redraw UV editor */
- if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
+ (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ }
/* XXX temp, first hack to get auto-render in compositor work (ton) */
WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
@@ -960,6 +977,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
{
char cmode = constraintModeToChar(t);
bool handled = false;
+ const int modifiers_prev = t->modifiers;
t->redraw |= handleMouseInput(t, &t->mouse, event);
@@ -1125,47 +1143,22 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
break;
case TFM_MODAL_AXIS_X:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- if (cmode == 'X') {
- stopConstraint(t);
- }
- else {
- if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X"));
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X"));
- }
- }
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ transform_event_xyz_constraint(t, XKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Y:
if ((t->flag & T_NO_CONSTRAINT) == 0) {
- if (cmode == 'Y') {
- stopConstraint(t);
- }
- else {
- if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y"));
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y"));
- }
- }
+ transform_event_xyz_constraint(t, YKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Z:
- if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- if (cmode == 'Z') {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z"));
- }
+ if ((t->flag & (T_NO_CONSTRAINT)) == 0) {
+ transform_event_xyz_constraint(t, ZKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
@@ -1511,6 +1504,13 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
+ /* if we change snap options, get the unsnapped values back */
+ if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
+ (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT)))
+ {
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
/* Per transform event, if present */
if (t->handleEvent &&
(!handled ||
@@ -1974,8 +1974,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
- if (RNA_struct_find_property(op->ptr, "proportional")) {
- RNA_enum_set(op->ptr, "proportional", proportional);
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ RNA_property_enum_set(op->ptr, prop, proportional);
RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
RNA_float_set(op->ptr, "proportional_size", t->prop_size);
}
@@ -2032,6 +2032,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
options |= CTX_TEXTURE;
}
}
+
+ if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_GPENCIL_STROKES;
+ }
+ }
t->options = options;
@@ -2163,6 +2169,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
case TFM_MASK_SHRINKFATTEN:
initMaskShrinkFatten(t);
break;
+ case TFM_GPENCIL_SHRINKFATTEN:
+ initGPShrinkFatten(t);
+ break;
case TFM_TRACKBALL:
initTrackball(t);
break;
@@ -2341,8 +2350,12 @@ int transformEnd(bContext *C, TransInfo *t)
/* handle restoring objects */
if (t->state == TRANS_CANCEL) {
/* exception, edge slide transformed UVs too */
- if (t->mode == TFM_EDGE_SLIDE)
+ if (t->mode == TFM_EDGE_SLIDE) {
doEdgeSlide(t, 0.0f);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ doVertSlide(t, 0.0f);
+ }
exit_code = OPERATOR_CANCELLED;
restoreTransObjects(t); // calls recalcData()
@@ -3139,7 +3152,7 @@ static void initResize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerResize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -3184,38 +3197,23 @@ static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
}
}
-/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */
-#define TX_FLIP_EPS 0.00001f
-BLI_INLINE int tx_sign(const float a)
-{
- return (a < -TX_FLIP_EPS ? 1 : a > TX_FLIP_EPS ? 2 : 3);
-}
-BLI_INLINE int tx_vec_sign_flip(const float a[3], const float b[3])
-{
- return ((tx_sign(a[0]) & tx_sign(b[0])) == 0 ||
- (tx_sign(a[1]) & tx_sign(b[1])) == 0 ||
- (tx_sign(a[2]) & tx_sign(b[2])) == 0);
-}
-
-/* smat is reference matrix, only scaled */
+/**
+ * \a smat is reference matrix only.
+ *
+ * \note this is a tricky area, before making changes see: T29633, T42444
+ */
static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
{
- float vec[3];
-
- copy_v3_v3(vec, mat[0]);
- size[0] = normalize_v3(vec);
- copy_v3_v3(vec, mat[1]);
- size[1] = normalize_v3(vec);
- copy_v3_v3(vec, mat[2]);
- size[2] = normalize_v3(vec);
-
+ float rmat[3][3];
+
+ mat3_to_rot_size(rmat, size, mat);
+
/* first tried with dotproduct... but the sign flip is crucial */
- if (tx_vec_sign_flip(mat[0], smat[0]) ) size[0] = -size[0];
- if (tx_vec_sign_flip(mat[1], smat[1]) ) size[1] = -size[1];
- if (tx_vec_sign_flip(mat[2], smat[2]) ) size[2] = -size[2];
+ if (dot_v3v3(rmat[0], smat[0]) < 0.0f) size[0] = -size[0];
+ if (dot_v3v3(rmat[1], smat[1]) < 0.0f) size[1] = -size[1];
+ if (dot_v3v3(rmat[2], smat[2]) < 0.0f) size[2] = -size[2];
}
-
static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
{
float tmat[3][3], smat[3][3], center[3];
@@ -4101,6 +4099,11 @@ static void initTranslation(TransInfo *t)
t->snap[1] = ED_node_grid_size() * NODE_GRID_STEPS;
t->snap[2] = ED_node_grid_size();
}
+ else if (t->spacetype == SPACE_IPO) {
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0;
+ t->snap[2] = 0.1f;
+ }
else {
t->snap[0] = 0.0f;
t->snap[1] = t->snap[2] = 1.0f;
@@ -4122,7 +4125,7 @@ static void initTranslation(TransInfo *t)
}
}
-static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerTranslation(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
size_t ofs = 0;
char tvec[NUM_STR_REP_LEN * 3];
@@ -4215,7 +4218,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]
}
}
-static void applyTranslationValue(TransInfo *t, float vec[3])
+static void applyTranslationValue(TransInfo *t, const float vec[3])
{
TransData *td = t->data;
float tvec[3];
@@ -4227,29 +4230,21 @@ static void applyTranslationValue(TransInfo *t, float vec[3])
if (td->flag & TD_SKIP)
continue;
-
+
/* handle snapping rotation before doing the translation */
if (usingSnappingNormal(t)) {
if (validSnappingNormal(t)) {
const float *original_normal;
- float axis[3];
- float quat[4];
float mat[3][3];
- float angle;
/* In pose mode, we want to align normals with Y axis of bones... */
if (t->flag & T_POSE)
original_normal = td->axismtx[1];
else
original_normal = td->axismtx[2];
-
- cross_v3_v3v3(axis, original_normal, t->tsnap.snapNormal);
- angle = saacos(dot_v3v3(original_normal, t->tsnap.snapNormal));
-
- axis_angle_to_quat(quat, axis, angle);
-
- quat_to_mat3(mat, quat);
-
+
+ rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
+
ElementRotation(t, td, mat, V3D_LOCAL);
}
else {
@@ -4681,6 +4676,83 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
/* -------------------------------------------------------------------- */
+/* Transform (GPencil Shrink/Fatten) */
+
+/** \name Transform GPencil Strokes Shrink/Fatten
+ * \{ */
+
+static void initGPShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_GPENCIL_SHRINKFATTEN;
+ t->transform = applyGPShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ 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
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ TransData *td = t->data;
+ float ratio;
+ int i;
+ char str[MAX_INFO_LEN];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %3f"), ratio);
+ }
+
+ for (i = 0; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f) *td->val = 0.001f;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
/* Transform (Push/Pull) */
/** \name Transform Push/Pull
@@ -4960,7 +5032,7 @@ static void initBoneSize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerBoneSize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
@@ -5130,6 +5202,220 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
}
/** \} */
+/* -------------------------------------------------------------------- */
+/* Original Data Store */
+
+/** \name Orig-Data Store Utility Functions
+ * \{ */
+
+static void slide_origdata_init_flag(
+ TransInfo *t, SlideOrigData *sod)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ 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) &&
+ CustomData_has_math(&bm->ldata))
+ {
+ sod->use_origfaces = true;
+ }
+ else {
+ sod->use_origfaces = false;
+ }
+}
+
+static void slide_origdata_init_data(
+ TransInfo *t, SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ sod->origfaces = BLI_ghash_ptr_new(__func__);
+ sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
+ }
+}
+
+static void slide_origdata_create_data_vert(
+ BMesh *bm, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+
+ /* copy face data */
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = BLI_array_alloca(loop_weights, l_num);
+ for (j = 0; j < l_num; j++) {
+ BMLoop *l = BM_iter_step(&liter);
+ if (!BLI_ghash_haskey(sod->origfaces, l->f)) {
+ BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
+ BLI_ghash_insert(sod->origfaces, l->f, f_copy);
+ }
+ loop_weights[j] = BM_loop_calc_face_angle(l);
+ }
+
+ /* store cd_loop_groups */
+ if (l_num != 0) {
+ sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ const int layer_nr = sod->layer_math_map[j];
+ sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(bm, sv->v, layer_nr, loop_weights, sod->arena);
+ }
+ }
+ else {
+ sv->cd_loop_groups = NULL;
+ }
+
+ BLI_ghash_insert(sod->origverts, sv->v, sv);
+}
+
+static void slide_origdata_create_data(
+ TransInfo *t, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+
+ int layer_index_dst;
+ int j;
+
+ /* over alloc, only 'math' layers are indexed */
+ sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
+ layer_index_dst = 0;
+ for (j = 0; j < bm->ldata.totlayer; j++) {
+ if (CustomData_layer_has_math(&bm->ldata, j)) {
+ sod->layer_math_map[layer_index_dst++] = j;
+ }
+ }
+ BLI_assert(layer_index_dst != 0);
+ sod->layer_math_map_num = layer_index_dst;
+
+ sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
+
+ for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+ slide_origdata_create_data_vert(bm, sod, sv);
+ }
+ }
+}
+
+/**
+ * If we're sliding the vert, return its original location, if not, the current location is good.
+ */
+static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v)
+{
+ TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
+ return sv ? sv->co_orig_3d : v->co;
+}
+
+static void slide_origdata_interp_data_vert(
+ SlideOrigData *sod, BMesh *bm, bool is_final,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+ const bool do_loop_weight = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->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(sod->origfaces, l->f);
+
+ /* 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, is_final);
+
+ /* make sure face-attributes are correct (e.g. MTexPoly) */
+ BM_elem_attrs_copy(sod->bm_origfaces, bm, f_copy, l->f);
+
+ /* weight the loop */
+ if (do_loop_weight) {
+ const float *v_prev = slide_origdata_orig_vert_co(sod, l->prev->v);
+ const float *v_next = slide_origdata_orig_vert_co(sod, l->next->v);
+ const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, v_prev, sv->co_orig_3d, v_next, f_copy->no);
+ const float eps = 0.00001f;
+ loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ }
+ }
+
+ if (do_loop_weight) {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
+ }
+ }
+ else {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
+ }
+ }
+}
+
+static void slide_origdata_interp_data(
+ TransInfo *t, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num,
+ bool is_final)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+
+ for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+
+ if (sv->cd_loop_groups) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+ }
+}
+
+static void slide_origdata_free_date(
+ SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ if (sod->bm_origfaces) {
+ BM_mesh_free(sod->bm_origfaces);
+ sod->bm_origfaces = NULL;
+ }
+
+ if (sod->origfaces) {
+ BLI_ghash_free(sod->origfaces, NULL, NULL);
+ sod->origfaces = NULL;
+ }
+
+ if (sod->origverts) {
+ BLI_ghash_free(sod->origverts, NULL, NULL);
+ sod->origverts = NULL;
+ }
+
+ if (sod->arena) {
+ BLI_memarena_free(sod->arena);
+ sod->arena = NULL;
+ }
+
+ MEM_SAFE_FREE(sod->layer_math_map);
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/* Transform (Edge Slide) */
@@ -5388,16 +5674,7 @@ static bool createEdgeSlideVerts(TransInfo *t)
rv3d = t->ar ? t->ar->regiondata : NULL;
}
- 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))
- {
- sld->use_origfaces = true;
- }
- else {
- sld->use_origfaces = false;
- }
+ slide_origdata_init_flag(t, &sld->orig_data);
sld->is_proportional = true;
sld->curr_sv_index = 0;
@@ -5789,30 +6066,12 @@ static bool createEdgeSlideVerts(TransInfo *t)
}
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
-
- if (sld->use_origfaces) {
- sld->origfaces = BLI_ghash_ptr_new(__func__);
- sld->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(sld->bm_origfaces, bm, NULL);
- }
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
/*create copies of faces for customdata projection*/
sv_array = sld->sv;
for (i = 0; i < sld->totsv; i++, sv_array++) {
- BMIter fiter;
- BMFace *f;
-
-
- if (sld->use_origfaces) {
- BM_ITER_ELEM (f, &fiter, sv_array->v, BM_FACES_OF_VERT) {
- if (!BLI_ghash_haskey(sld->origfaces, f)) {
- BMFace *f_copy = BM_face_copy(sld->bm_origfaces, bm, f, true, true);
- BLI_ghash_insert(sld->origfaces, f, f_copy);
- }
- }
- }
-
/* switch a/b if loop direction is different from global direction */
l_nr = sv_array->loop_nr;
if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
@@ -5856,172 +6115,27 @@ static bool createEdgeSlideVerts(TransInfo *t)
void projectEdgeSlideData(TransInfo *t, bool is_final)
{
EdgeSlideData *sld = t->customData;
- TransDataEdgeSlideVert *sv;
- BMEditMesh *em = sld->em;
- int i;
+ SlideOrigData *sod = &sld->orig_data;
- if (sld->use_origfaces == false) {
+ if (sod->use_origfaces == false) {
return;
}
- for (i = 0, sv = sld->sv; i < sld->totsv; sv++, i++) {
- BMIter fiter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &fiter, sv->v, BM_LOOPS_OF_VERT) {
- BMFace *f_copy; /* the copy of 'f' */
- BMFace *f_copy_flip; /* the copy of 'f' or detect if we need to flip to the shorter side. */
-
- f_copy = BLI_ghash_lookup(sld->origfaces, l->f);
-
- /* project onto copied projection face */
- f_copy_flip = f_copy;
-
- if (BM_elem_flag_test(l->e, BM_ELEM_SELECT) || BM_elem_flag_test(l->prev->e, BM_ELEM_SELECT)) {
- /* the loop is attached of the selected edges that are sliding */
- BMLoop *l_ed_sel = l;
-
- if (!BM_elem_flag_test(l->e, BM_ELEM_SELECT))
- l_ed_sel = l_ed_sel->prev;
-
- if (sld->perc < 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_b)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
- }
- }
- else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_a)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
- }
- }
-
- BLI_assert(f_copy_flip != NULL);
- if (!f_copy_flip) {
- continue; /* shouldn't happen, but protection */
- }
- }
- else {
- /* the loop is attached to only one vertex and not a selected edge,
- * this means we have to find a selected edges face going in the right direction
- * to copy from else we get bad distortion see: [#31080] */
- BMIter eiter;
- BMEdge *e_sel;
-
- BLI_assert(l->v == sv->v);
- BM_ITER_ELEM (e_sel, &eiter, sv->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_sel, BM_ELEM_SELECT)) {
- break;
- }
- }
-
- if (e_sel) {
- /* warning if the UV's are not contiguous, this will copy from the _wrong_ UVs
- * in fact whenever the face being copied is not 'f_copy' this can happen,
- * we could be a lot smarter about this but would need to deal with every UV channel or
- * add a way to mask out lauers when calling #BM_loop_interp_from_face() */
-
- /*
- * + +----------------+
- * \ | |
- * (this) l_adj| |
- * \ | |
- * \| e_sel |
- * +----------+----------------+ <- the edge we are sliding.
- * /|sv->v |
- * / | |
- * (or) l_adj| |
- * / | |
- * + +----------------+
- * (above)
- * 'other connected loops', attached to sv->v slide faces.
- *
- * NOTE: The faces connected to the edge may not have contiguous UV's
- * so step around the loops to find l_adj.
- * However if the 'other loops' are not cotiguous it will still give problems.
- *
- * A full solution to this would have to store
- * per-customdata-layer map of which loops are contiguous
- * and take this into account when interpolating.
- *
- * NOTE: If l_adj's edge isnt manifold then use then
- * interpolate the loop from its own face.
- * Can happen when 'other connected loops' are disconnected from the face-fan.
- */
-
- BMLoop *l_adj = NULL;
- if (sld->perc < 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_b)) {
- l_adj = e_sel->l;
- }
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_b)) {
- l_adj = e_sel->l->radial_next;
- }
- }
- else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_a)) {
- l_adj = e_sel->l;
- }
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_a)) {
- l_adj = e_sel->l->radial_next;
- }
- }
-
- /* step across to the face */
- if (l_adj) {
- l_adj = BM_loop_other_edge_loop(l_adj, sv->v);
- if (!BM_edge_is_boundary(l_adj->e)) {
- l_adj = l_adj->radial_next;
- }
- else {
- /* disconnected face-fan, fallback to self */
- l_adj = l;
- }
-
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_adj->f);
- }
- }
- }
-
- /* 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(em->bm, l, f_copy_flip, false, false);
-
- if (is_final) {
- BM_loop_interp_multires(em->bm, l, f_copy_flip);
- if (f_copy != f_copy_flip) {
- BM_loop_interp_multires(em->bm, l, f_copy);
- }
- }
-
- /* make sure face-attributes are correct (e.g. MTexPoly) */
- BM_elem_attrs_copy(sld->bm_origfaces, em->bm, f_copy, l->f);
- }
- }
+ slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
- if (sld->use_origfaces) {
- if (sld->bm_origfaces) {
- BM_mesh_free(sld->bm_origfaces);
- sld->bm_origfaces = NULL;
- }
-
- if (sld->origfaces) {
- BLI_ghash_free(sld->origfaces, NULL, NULL);
- sld->origfaces = NULL;
- }
- }
+ slide_origdata_free_date(&sld->orig_data);
}
-
void freeEdgeSlideVerts(TransInfo *t)
{
EdgeSlideData *sld = t->customData;
if (!sld)
return;
-
+
freeEdgeSlideTempFaces(sld);
bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
@@ -6195,7 +6309,7 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
}
}
-static int doEdgeSlide(TransInfo *t, float perc)
+static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideData *sld = t->customData;
TransDataEdgeSlideVert *svlist = sld->sv, *sv;
@@ -6252,8 +6366,6 @@ static int doEdgeSlide(TransInfo *t, float perc)
}
projectEdgeSlideData(t, 0);
-
- return 1;
}
static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
@@ -6418,6 +6530,8 @@ static bool createVertSlideVerts(TransInfo *t)
rv3d = ar ? ar->regiondata : NULL;
}
+ slide_origdata_init_flag(t, &sld->orig_data);
+
sld->is_proportional = true;
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
@@ -6513,6 +6627,10 @@ static bool createVertSlideVerts(TransInfo *t)
sld->sv = sv_array;
sld->totsv = j;
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
sld->em = em;
sld->perc = 0.0f;
@@ -6527,6 +6645,23 @@ static bool createVertSlideVerts(TransInfo *t)
return true;
}
+void projectVertSlideData(TransInfo *t, bool is_final)
+{
+ VertSlideData *sld = t->customData;
+ SlideOrigData *sod = &sld->orig_data;
+
+ if (sod->use_origfaces == false) {
+ return;
+ }
+
+ slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
+}
+
+void freeVertSlideTempFaces(VertSlideData *sld)
+{
+ slide_origdata_free_date(&sld->orig_data);
+}
+
void freeVertSlideVerts(TransInfo *t)
{
VertSlideData *sld = t->customData;
@@ -6534,6 +6669,9 @@ void freeVertSlideVerts(TransInfo *t)
if (!sld)
return;
+ freeVertSlideTempFaces(sld);
+
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (sld->totsv > 0) {
TransDataVertSlideVert *sv = sld->sv;
@@ -6643,7 +6781,7 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
#endif
case MOUSEMOVE:
{
- /* don't recalculat the best edge */
+ /* don't recalculate the best edge */
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
if (is_clamp) {
calcVertSlideMouseActiveEdges(t, event->mval);
@@ -6730,7 +6868,7 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t)
}
}
-static int doVertSlide(TransInfo *t, float perc)
+static void doVertSlide(TransInfo *t, float perc)
{
VertSlideData *sld = t->customData;
TransDataVertSlideVert *svlist = sld->sv, *sv;
@@ -6770,7 +6908,7 @@ static int doVertSlide(TransInfo *t, float perc)
}
}
- return 1;
+ projectVertSlideData(t, false);
}
static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
@@ -7145,7 +7283,7 @@ static void initSeqSlide(TransInfo *t)
t->num.unit_type[1] = B_UNIT_NONE;
}
-static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
+static void headerSeqSlide(TransInfo *t, const float val[2], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -7169,10 +7307,11 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
}
-static void applySeqSlideValue(TransInfo *t, const float val[2])
+static void applySeqSlideValue(TransInfo *t, const float val[2], int frame)
{
TransData *td = t->data;
int i;
+ TransSeq *ts = t->customData;
for (i = 0; i < t->total; i++, td++) {
float tvec[2];
@@ -7187,15 +7326,21 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
mul_v2_fl(tvec, td->factor);
- td->loc[0] = td->iloc[0] + tvec[0];
+ if (t->modifiers & MOD_SNAP_INVERT) {
+ td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min);
+ }
+ else {
+ td->loc[0] = td->iloc[0] + tvec[0];
+ }
+
td->loc[1] = td->iloc[1] + tvec[1];
}
}
-static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
+static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[MAX_INFO_LEN];
-
+ int snap_frame = 0;
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
float tvec[3];
@@ -7203,7 +7348,8 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
copy_v3_v3(t->values, tvec);
}
else {
- snapGridIncrement(t, t->values);
+ snap_frame = snapSequenceBounds(t, mval);
+ // snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}
@@ -7211,7 +7357,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
t->values[1] = floor(t->values[1] + 0.5f);
headerSeqSlide(t, t->values, str);
- applySeqSlideValue(t, t->values);
+ applySeqSlideValue(t, t->values, snap_frame);
recalcData(t);
@@ -7536,7 +7682,7 @@ static void initTimeSlide(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
}
-static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN])
+static void headerTimeSlide(TransInfo *t, const float sval, char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];