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.h46
-rw-r--r--source/blender/editors/transform/transform_convert.c177
-rw-r--r--source/blender/editors/transform/transform_convert.h7
-rw-r--r--source/blender/editors/transform/transform_convert_cursor.c26
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c6
-rw-r--r--source/blender/editors/transform/transform_convert_mball.c20
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c1198
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_skin.c28
-rw-r--r--source/blender/editors/transform/transform_generics.c2
-rw-r--r--source/blender/editors/transform/transform_mode.c2
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c1
-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.c1
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c1
-rw-r--r--source/blender/editors/transform/transform_snap.c6
-rw-r--r--source/blender/editors/transform/transform_snap_object.c667
19 files changed, 1114 insertions, 1080 deletions
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index f2d5800abb7..090b8b83dcc 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,51 +104,50 @@ 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 */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index c021c084a23..98db27c83f7 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1122,8 +1122,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 +1471,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 +1641,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 +1707,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_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..f294bbbf0aa 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);
}
@@ -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_mball.c b/source/blender/editors/transform/transform_convert_mball.c
index 6f5c0318054..e47cf4edc4a 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, 0); /* sets recalc flags */
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 93c36645873..9ef033639f6 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
@@ -727,10 +1295,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 +1337,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 +1527,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 +1600,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)
+static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc)
{
- 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)
-{
- 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,20 +1641,24 @@ 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) {
@@ -1660,7 +1682,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..68305c45280 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,8 +292,8 @@ 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);
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index c0c4b22da98..c9b6bef5904 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -538,7 +538,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..867a6cc4291 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -1263,7 +1263,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`.
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_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..fcdc57a98e2 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;
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_snap.c b/source/blender/editors/transform/transform_snap.c
index d0f91802fff..193954fffb6 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -345,7 +345,7 @@ void applyProject(TransInfo *t)
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
.use_occlusion_test = false,
.use_backface_culling = t->tsnap.use_backface_culling,
},
@@ -1167,7 +1167,7 @@ short snapObjectsTransform(
t->settings->snap_mode,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
.use_occlusion_test = t->settings->snap_mode != SCE_SNAP_MODE_FACE,
.use_backface_culling = t->tsnap.use_backface_culling,
},
@@ -1201,7 +1201,7 @@ bool peelObjectsTransform(TransInfo *t,
t->depsgraph,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
},
mval,
-1.0f,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index e5f6f207e3c..512f912a532 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -44,6 +44,7 @@
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
#include "BKE_geometry_set.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@@ -145,9 +146,37 @@ struct SnapObjectContext {
/** \name Utilities
* \{ */
-static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em)
+/* Mesh used for snapping.
+ * If NULL the BMesh should be used. */
+static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
{
- return (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH);
+ Mesh *me_eval = ob_eval->data;
+ bool use_hide = false;
+ if (BKE_object_is_in_editmode(ob_eval)) {
+ if (edit_mode_type == SNAP_GEOM_EDIT) {
+ return NULL;
+ }
+
+ BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
+ if ((edit_mode_type == SNAP_GEOM_FINAL) && em_eval->mesh_eval_final) {
+ if (em_eval->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
+ return NULL;
+ }
+ me_eval = em_eval->mesh_eval_final;
+ use_hide = true;
+ }
+ else if ((edit_mode_type == SNAP_GEOM_CAGE) && em_eval->mesh_eval_cage) {
+ if (em_eval->mesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
+ return NULL;
+ }
+ me_eval = em_eval->mesh_eval_cage;
+ use_hide = true;
+ }
+ }
+ if (r_use_hide) {
+ *r_use_hide = use_hide;
+ }
+ return me_eval;
}
/** \} */
@@ -209,30 +238,69 @@ static void snap_object_data_clear(SnapObjectData *sod)
memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type));
}
-static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob)
+static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob_eval)
{
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval);
if (sod == NULL) {
if (sctx->cache.data_to_object_map != NULL) {
- ob = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob->data);
+ ob_eval = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data);
/* Could be NULl when mixing edit-mode and non edit-mode objects. */
- if (ob != NULL) {
- sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ if (ob_eval != NULL) {
+ sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval);
}
}
}
return sod;
}
-static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
+static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
+ Object *ob_eval,
+ Mesh *me_eval,
+ bool use_hide)
{
SnapObjectData *sod;
void **sod_p;
bool init = false;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) {
sod = *sod_p;
+ bool is_dirty = false;
if (sod->type != SNAP_MESH) {
+ is_dirty = true;
+ }
+ else if (sod->treedata_mesh.tree && sod->treedata_mesh.cached &&
+ !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->treedata_mesh.tree)) {
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ is_dirty = true;
+ }
+ else if (sod->bvhtree[0] && sod->cached[0] &&
+ !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[0])) {
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ is_dirty = true;
+ }
+ else if (sod->bvhtree[1] && sod->cached[1] &&
+ !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[1])) {
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ is_dirty = true;
+ }
+ else if (!sod->treedata_mesh.looptri_allocated &&
+ sod->treedata_mesh.looptri != me_eval->runtime.looptris.array) {
+ is_dirty = true;
+ }
+ else if (!sod->treedata_mesh.vert_allocated && sod->treedata_mesh.vert != me_eval->mvert) {
+ is_dirty = true;
+ }
+ else if (!sod->treedata_mesh.loop_allocated && sod->treedata_mesh.loop != me_eval->mloop) {
+ is_dirty = true;
+ }
+ else if (!sod->treedata_mesh.edge_allocated && sod->treedata_mesh.edge != me_eval->medge) {
+ is_dirty = true;
+ }
+ else if (sod->poly != me_eval->mpoly) {
+ is_dirty = true;
+ }
+
+ if (is_dirty) {
snap_object_data_clear(sod);
init = true;
}
@@ -244,8 +312,32 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object
if (init) {
sod->type = SNAP_MESH;
- /* start assuming that it has each of these element types */
- sod->has_looptris = true;
+
+ /* The BVHTree from looptris is always required. */
+ BLI_assert(sod->treedata_mesh.tree == NULL);
+ BKE_bvhtree_from_mesh_get(&sod->treedata_mesh,
+ me_eval,
+ use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI,
+ 4);
+
+ if (sod->treedata_mesh.tree == NULL) {
+ sod->treedata_mesh.vert = me_eval->mvert;
+ sod->treedata_mesh.loop = me_eval->mloop;
+ sod->treedata_mesh.looptri = BKE_mesh_runtime_looptri_ensure(me_eval);
+ BLI_assert(sod->has_looptris == false);
+ }
+ else {
+ BLI_assert(sod->treedata_mesh.vert != NULL);
+ BLI_assert(sod->treedata_mesh.loop != NULL);
+ BLI_assert(sod->treedata_mesh.looptri != NULL);
+ sod->has_looptris = true;
+ }
+
+ /* Required for snapping with occlusion. */
+ sod->treedata_mesh.edge = me_eval->medge;
+ sod->poly = me_eval->mpoly;
+
+ /* Start assuming that it has each of these element types. */
sod->has_loose_edge = true;
sod->has_loose_vert = true;
}
@@ -253,26 +345,26 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object
return sod;
}
-static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob)
+static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob_eval)
{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (em->mesh_eval_final) {
- return &em->mesh_eval_final->runtime;
+ BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
+ if (em_eval->mesh_eval_final) {
+ return &em_eval->mesh_eval_final->runtime;
}
- if (em->mesh_eval_cage) {
- return &em->mesh_eval_cage->runtime;
+ if (em_eval->mesh_eval_cage) {
+ return &em_eval->mesh_eval_cage->runtime;
}
- return &((Mesh *)ob->data)->runtime;
+ return &((Mesh *)ob_eval->data)->runtime;
}
static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
- Object *ob,
+ Object *ob_eval,
BMEditMesh *em)
{
SnapObjectData *sod;
void **sod_p;
- bool init = false, init_min_max = true, clear_cache = false;
+ bool init = false;
{
/* Use object-data as the key in ghash since the editmesh
@@ -281,48 +373,53 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__);
}
void **ob_p;
- if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob->data, &ob_p)) {
- ob = *ob_p;
+ if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob_eval->data, &ob_p)) {
+ ob_eval = *ob_p;
}
else {
- *ob_p = ob;
+ *ob_p = ob_eval;
}
}
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) {
sod = *sod_p;
- bool clear = false;
+ bool is_dirty = false;
/* Check if the geometry has changed. */
if (sod->type != SNAP_EDIT_MESH) {
- clear = true;
+ is_dirty = true;
}
else if (sod->treedata_editmesh.em != em) {
- clear_cache = true;
- init = true;
+ is_dirty = true;
}
else if (sod->mesh_runtime) {
- if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob)) {
- clear_cache = true;
- init = true;
+ if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob_eval)) {
+ if (G.moving) {
+ /* Hack to avoid updating while transforming. */
+ BLI_assert(!sod->treedata_editmesh.cached && !sod->cached[0] && !sod->cached[1]);
+ sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval);
+ }
+ else {
+ is_dirty = true;
+ }
}
else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
!bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
- clear = true;
+ is_dirty = true;
}
else if (sod->bvhtree[0] && sod->cached[0] &&
!bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
- clear = true;
+ is_dirty = true;
}
else if (sod->bvhtree[1] && sod->cached[1] &&
!bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
- clear = true;
+ is_dirty = true;
}
}
- if (clear) {
+ if (is_dirty) {
snap_object_data_clear(sod);
init = true;
}
@@ -335,27 +432,8 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
if (init) {
sod->type = SNAP_EDIT_MESH;
sod->treedata_editmesh.em = em;
-
- if (clear_cache) {
- /* Only init min and max when you have a non-custom bvhtree pending. */
- init_min_max = false;
- if (sod->treedata_editmesh.cached) {
- sod->treedata_editmesh.tree = NULL;
- init_min_max = true;
- }
- for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
- if (sod->cached[i]) {
- sod->bvhtree[i] = NULL;
- init_min_max = true;
- }
- }
- }
-
- if (init_min_max) {
- bm_mesh_minmax(em->bm, sod->min, sod->max);
- }
-
- sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob);
+ sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval);
+ bm_mesh_minmax(em->bm, sod->min, sod->max);
}
return sod;
@@ -368,9 +446,9 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
* \{ */
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
- Object *ob,
+ Object *ob_eval,
float obmat[4][4],
- bool use_obedit,
+ eSnapEditType edit_mode_type,
bool use_backface_culling,
bool is_object_active,
void *data);
@@ -387,10 +465,17 @@ static void iter_snap_objects(SnapObjectContext *sctx,
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
const View3D *v3d = sctx->v3d_data.v3d;
const eSnapSelect snap_select = params->snap_select;
- const bool use_object_edit_cage = params->use_object_edit_cage;
+ const eSnapEditType edit_mode_type = params->edit_mode_type;
const bool use_backface_culling = params->use_backface_culling;
Base *base_act = view_layer->basact;
+ if (snap_select == SNAP_ONLY_ACTIVE) {
+ Object *obj_eval = DEG_get_evaluated_object(depsgraph, base_act->object);
+ sob_callback(
+ sctx, obj_eval, obj_eval->obmat, edit_mode_type, use_backface_culling, true, data);
+ return;
+ }
+
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
if (!BASE_VISIBLE(v3d, base)) {
continue;
@@ -425,7 +510,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
sob_callback(sctx,
dupli_ob->ob,
dupli_ob->mat,
- use_object_edit_cage,
+ edit_mode_type,
use_backface_culling,
is_object_active,
data);
@@ -436,7 +521,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
sob_callback(sctx,
obj_eval,
obj_eval->obmat,
- use_object_edit_cage,
+ edit_mode_type,
use_backface_culling,
is_object_active,
data);
@@ -464,7 +549,7 @@ struct RayCastAll_Data {
float len_diff;
float local_scale;
- Object *ob;
+ Object *ob_eval;
uint ob_uuid;
/* output data */
@@ -476,7 +561,7 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth,
const float co[3],
const float no[3],
int index,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
uint ob_uuid)
{
@@ -487,7 +572,7 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth,
copy_v3_v3(hit->no, no);
hit->index = index;
- hit->ob = ob;
+ hit->ob_eval = ob_eval;
copy_m4_m4(hit->obmat, (float(*)[4])obmat);
hit->ob_uuid = ob_uuid;
@@ -529,7 +614,7 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
normalize_v3(normal);
struct SnapObjectHitDepth *hit_item = hit_depth_create(
- depth, location, normal, hit->index, data->ob, data->obmat, data->ob_uuid);
+ depth, location, normal, hit->index, data->ob_eval, data->obmat, data->ob_uuid);
BLI_addtail(data->hit_list, hit_item);
}
}
@@ -601,8 +686,8 @@ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
static bool raycastMesh(SnapObjectContext *sctx,
const float ray_start[3],
const float ray_dir[3],
- Object *ob,
- Mesh *me,
+ Object *ob_eval,
+ Mesh *me_eval,
const float obmat[4][4],
const uint ob_index,
bool use_hide,
@@ -617,7 +702,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
{
bool retval = false;
- if (me->totpoly == 0) {
+ if (me_eval->totpoly == 0) {
return retval;
}
@@ -641,7 +726,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
}
/* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ BoundBox *bb = BKE_mesh_boundbox_get(ob_eval);
if (bb) {
/* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
if (!isect_ray_aabb_v3_simple(
@@ -661,53 +746,18 @@ static bool raycastMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
- SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide);
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
- /* The tree is owned by the Mesh and may have been freed since we last used. */
- if (treedata->tree) {
- BLI_assert(treedata->cached);
- if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- else {
- /* Update Pointers. */
- if (treedata->vert && treedata->vert_allocated == false) {
- treedata->vert = me->mvert;
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop;
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
- }
- }
-
if (treedata->tree == NULL) {
- if (use_hide) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI_NO_HIDDEN, 4);
- }
- else {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
- }
-
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
-
- if (treedata->tree == NULL) {
- return retval;
- }
+ return retval;
}
float timat[3][3]; /* transpose inverse matrix for normals */
transpose_m3_m4(timat, imat);
+ BLI_assert(treedata->raycast_callback != NULL);
if (r_hit_list) {
struct RayCastAll_Data data;
@@ -717,7 +767,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
data.timat = timat;
data.len_diff = len_diff;
data.local_scale = local_scale;
- data.ob = ob;
+ data.ob_eval = ob_eval;
data.ob_uuid = ob_index;
data.hit_list = r_hit_list;
data.retval = retval;
@@ -776,7 +826,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
static bool raycastEditMesh(SnapObjectContext *sctx,
const float ray_start[3],
const float ray_dir[3],
- Object *ob,
+ Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
const uint ob_index,
@@ -813,7 +863,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
local_depth *= local_scale;
}
- SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
/* Test BoundBox */
@@ -839,7 +889,8 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
if (treedata->tree == NULL) {
/* Operators only update the editmesh looptris of the original mesh. */
- BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob)));
+ BLI_assert(sod->treedata_editmesh.em ==
+ BKE_editmesh_from_object(DEG_get_original_object(ob_eval)));
em = sod->treedata_editmesh.em;
if (sctx->callbacks.edit_mesh.test_face_fn) {
@@ -886,7 +937,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
data.timat = timat;
data.len_diff = len_diff;
data.local_scale = local_scale;
- data.ob = ob;
+ data.ob_eval = ob_eval;
data.ob_uuid = ob_index;
data.hit_list = r_hit_list;
data.retval = retval;
@@ -967,9 +1018,9 @@ struct RaycastObjUserData {
* \note Duplicate args here are documented at #snapObjectsRay
*/
static void raycast_obj_fn(SnapObjectContext *sctx,
- Object *ob,
+ Object *ob_eval,
float obmat[4][4],
- bool use_obedit,
+ eSnapEditType edit_mode_type,
bool use_backface_culling,
bool is_object_active,
void *data)
@@ -982,53 +1033,46 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
bool retval = false;
if (use_occlusion_test) {
- if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) {
+ if ((edit_mode_type == SNAP_GEOM_EDIT) && sctx->use_v3d &&
+ XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) {
/* Use of occlude geometry in editing mode disabled. */
return;
}
- if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
+ if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) {
/* Do not hit objects that are in wire or bounding box
* display mode. */
return;
}
}
- switch (ob->type) {
+ switch (ob_eval->type) {
case OB_MESH: {
- Mesh *me = ob->data;
bool use_hide = false;
- if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
- /* Operators only update the editmesh looptris of the original mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
- retval = raycastEditMesh(sctx,
- dt->ray_start,
- dt->ray_dir,
- ob,
- em_orig,
- obmat,
- ob_index,
- use_backface_culling,
- ray_depth,
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_hit_list);
- break;
- }
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- use_hide = true;
- }
+ Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
+ if (me_eval == NULL) {
+ /* Operators only update the editmesh looptris of the original mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval));
+ retval = raycastEditMesh(sctx,
+ dt->ray_start,
+ dt->ray_dir,
+ ob_eval,
+ em_orig,
+ obmat,
+ ob_index,
+ use_backface_culling,
+ ray_depth,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
+ break;
}
retval = raycastMesh(sctx,
dt->ray_start,
dt->ray_dir,
- ob,
- me,
+ ob_eval,
+ me_eval,
obmat,
ob_index,
use_hide,
@@ -1044,12 +1088,12 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
case OB_SURF:
case OB_FONT: {
if (!is_object_active) {
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (mesh_eval) {
retval = raycastMesh(sctx,
dt->ray_start,
dt->ray_dir,
- ob,
+ ob_eval,
mesh_eval,
obmat,
ob_index,
@@ -1068,7 +1112,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
if (retval) {
if (dt->r_ob) {
- *dt->r_ob = ob;
+ *dt->r_ob = ob_eval;
}
if (dt->r_obmat) {
copy_m4_m4(dt->r_obmat, obmat);
@@ -1323,6 +1367,33 @@ typedef struct Nearest2dUserData {
bool use_backface_culling;
} Nearest2dUserData;
+static void nearest2d_data_init(SnapObjectData *sod,
+ bool is_persp,
+ bool use_backface_culling,
+ Nearest2dUserData *r_nearest2d)
+{
+ if (sod->type == SNAP_MESH) {
+ r_nearest2d->userdata = &sod->treedata_mesh;
+ r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
+ r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
+ r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
+ r_nearest2d->get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get;
+ r_nearest2d->get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get;
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ r_nearest2d->userdata = sod->treedata_editmesh.em;
+ r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
+ r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
+ r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
+ r_nearest2d->get_tri_verts_index = NULL;
+ r_nearest2d->get_tri_edges_index = NULL;
+ }
+
+ r_nearest2d->is_persp = is_persp;
+ r_nearest2d->use_backface_culling = use_backface_culling;
+}
+
static void cb_snap_vert(void *userdata,
int index,
const struct DistProjectedAABBPrecalc *precalc,
@@ -1470,7 +1541,7 @@ static void cb_snap_tri_verts(void *userdata,
static short snap_mesh_polygon(SnapObjectContext *sctx,
SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
bool use_backface_culling,
/* read/write args */
@@ -1495,28 +1566,21 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .use_backface_culling = use_backface_culling,
- };
-
BVHTreeNearest nearest = {
.index = -1,
.dist_sq = square_f(*dist_px),
};
- SnapObjectData *sod = snap_object_data_lookup(sctx, ob);
-
+ SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval);
BLI_assert(sod != NULL);
+ Nearest2dUserData nearest2d;
+ nearest2d_data_init(
+ sod, snapdata->view_proj == VIEW_PROJ_PERSP, use_backface_culling, &nearest2d);
+
if (sod->type == SNAP_MESH) {
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
- nearest2d.userdata = treedata;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
-
const MPoly *mp = &sod->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
@@ -1547,11 +1611,6 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BLI_assert(sod->type == SNAP_EDIT_MESH);
BMEditMesh *em = sod->treedata_editmesh.em;
- nearest2d.userdata = em;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
-
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
BMFace *f = BM_face_at_index(em->bm, *r_index);
BMLoop *l_iter, *l_first;
@@ -1608,7 +1667,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
float original_dist_px,
const float prev_co[3],
@@ -1622,32 +1681,16 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
{
short elem = SCE_SNAP_MODE_EDGE;
- if (ob->type != OB_MESH) {
+ if (ob_eval->type != OB_MESH) {
return elem;
}
- SnapObjectData *sod = snap_object_data_lookup(sctx, ob);
-
+ SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval);
BLI_assert(sod != NULL);
Nearest2dUserData nearest2d;
- {
- nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- nearest2d.use_backface_culling = use_backface_culling;
- if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &sod->treedata_mesh;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = sod->treedata_editmesh.em;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
- }
- }
+ nearest2d_data_init(
+ sod, snapdata->view_proj == VIEW_PROJ_PERSP, use_backface_culling, &nearest2d);
int vindex[2];
nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
@@ -1772,9 +1815,8 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
}
static short snapArmature(SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
- bool use_obedit,
/* read/write args */
float *dist_px,
/* return args */
@@ -1795,11 +1837,11 @@ static short snapArmature(SnapData *snapdata,
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+ bool use_obedit = ((bArmature *)ob_eval->data)->edbo != NULL;
if (use_obedit == false) {
/* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
+ BoundBox *bb = BKE_armature_boundbox_get(ob_eval);
if (bb && !snap_bound_box_check_dist(
bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
return retval;
@@ -1814,7 +1856,7 @@ static short snapArmature(SnapData *snapdata,
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- bArmature *arm = ob->data;
+ bArmature *arm = ob_eval->data;
if (arm->edbo) {
LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
if (eBone->layer & arm->layer) {
@@ -1858,8 +1900,8 @@ static short snapArmature(SnapData *snapdata,
}
}
}
- else if (ob->pose && ob->pose->chanbase.first) {
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ else if (ob_eval->pose && ob_eval->pose->chanbase.first) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_eval->pose->chanbase) {
Bone *bone = pchan->bone;
/* skip hidden bones */
if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
@@ -1917,7 +1959,7 @@ static short snapArmature(SnapData *snapdata,
}
static short snapCurve(SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
bool use_obedit,
/* read/write args */
@@ -1934,7 +1976,7 @@ static short snapCurve(SnapData *snapdata,
return 0;
}
- Curve *cu = ob->data;
+ Curve *cu = ob_eval->data;
float dist_px_sq = square_f(*dist_px);
float lpmat[4][4];
@@ -1944,11 +1986,11 @@ static short snapCurve(SnapData *snapdata,
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob_eval);
if (use_obedit == false) {
/* Test BoundBox */
- BoundBox *bb = BKE_curve_boundbox_get(ob);
+ BoundBox *bb = BKE_curve_boundbox_get(ob_eval);
if (bb && !snap_bound_box_check_dist(
bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
return 0;
@@ -2068,7 +2110,7 @@ static short snapCurve(SnapData *snapdata,
/* may extend later (for now just snaps to empty center) */
static short snap_object_center(SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
const float obmat[4][4],
/* read/write args */
float *dist_px,
@@ -2079,7 +2121,7 @@ static short snap_object_center(SnapData *snapdata,
{
short retval = 0;
- if (ob->transflag & OB_DUPLI) {
+ if (ob_eval->transflag & OB_DUPLI) {
return retval;
}
@@ -2222,9 +2264,10 @@ static short snapCamera(const SnapObjectContext *sctx,
static short snapMesh(SnapObjectContext *sctx,
SnapData *snapdata,
- Object *ob,
- Mesh *me,
+ Object *ob_eval,
+ Mesh *me_eval,
const float obmat[4][4],
+ bool use_hide,
bool use_backface_culling,
/* read/write args */
float *dist_px,
@@ -2234,10 +2277,10 @@ static short snapMesh(SnapObjectContext *sctx,
int *r_index)
{
BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
- if (me->totvert == 0) {
+ if (me_eval->totvert == 0) {
return 0;
}
- if (me->totedge == 0 && !(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ if (me_eval->totedge == 0 && !(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
return 0;
}
@@ -2247,65 +2290,46 @@ static short snapMesh(SnapObjectContext *sctx,
float dist_px_sq = square_f(*dist_px);
/* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ BoundBox *bb = BKE_mesh_boundbox_get(ob_eval);
if (bb && !snap_bound_box_check_dist(
bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
return 0;
}
- SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide);
- BVHTreeFromMesh *treedata, dummy_treedata;
+ BVHTreeFromMesh *treedata, treedata_tmp;
treedata = &sod->treedata_mesh;
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata->cached && treedata->tree &&
- !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- if (sod->cached[0] && sod->bvhtree[0] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) {
- sod->bvhtree[0] = NULL;
- }
- if (sod->cached[1] && sod->bvhtree[1] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) {
- sod->bvhtree[1] = NULL;
- }
-
- if (sod->has_looptris && treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
- sod->has_looptris = (treedata->tree != NULL);
- if (sod->has_looptris) {
- /* Make sure that the array of edges is referenced in the callbacks. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- }
if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
- sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
- sod->has_loose_edge = sod->bvhtree[0] != NULL;
- sod->cached[0] = dummy_treedata.cached;
-
- if (sod->has_loose_edge) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
-
- BLI_assert(treedata->edge_allocated == false);
- treedata->edge = dummy_treedata.edge;
- treedata->edge_allocated = dummy_treedata.edge_allocated;
+ sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(
+ &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2);
+ if (sod->bvhtree[0] == NULL) {
+ sod->has_loose_edge = false;
}
+ sod->cached[0] = treedata_tmp.cached;
+ BLI_assert(!ELEM(true,
+ treedata_tmp.vert_allocated,
+ treedata_tmp.edge_allocated,
+ treedata_tmp.face_allocated,
+ treedata_tmp.loop_allocated,
+ treedata_tmp.looptri_allocated));
}
+
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
- sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
- sod->has_loose_vert = sod->bvhtree[1] != NULL;
- sod->cached[1] = dummy_treedata.cached;
-
- if (sod->has_loose_vert) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
+ sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(
+ &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2);
+ if (sod->bvhtree[1] == NULL) {
+ sod->has_loose_vert = false;
}
+ sod->cached[1] = treedata_tmp.cached;
+ BLI_assert(!ELEM(true,
+ treedata_tmp.vert_allocated,
+ treedata_tmp.edge_allocated,
+ treedata_tmp.face_allocated,
+ treedata_tmp.loop_allocated,
+ treedata_tmp.looptri_allocated));
}
}
else {
@@ -2313,33 +2337,9 @@ static short snapMesh(SnapObjectContext *sctx,
sod->has_loose_vert = false;
}
- /* Update pointers. */
- if (treedata->vert_allocated == false) {
- treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
- }
- if (treedata->tree || sod->bvhtree[0]) {
- if (treedata->edge_allocated == false) {
- /* If raycast has been executed before, `treedata->edge` can be NULL. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- }
-
- Nearest2dUserData nearest2d = {
- .userdata = treedata,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
- .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
- .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .use_backface_culling = use_backface_culling,
- };
+ Nearest2dUserData nearest2d;
+ nearest2d_data_init(
+ sod, snapdata->view_proj == VIEW_PROJ_PERSP, use_backface_culling, &nearest2d);
BVHTreeNearest nearest = {
.index = -1,
@@ -2455,7 +2455,7 @@ static short snapMesh(SnapObjectContext *sctx,
static short snapEditMesh(SnapObjectContext *sctx,
SnapData *snapdata,
- Object *ob,
+ Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
bool use_backface_culling,
@@ -2484,7 +2484,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
float dist_px_sq = square_f(*dist_px);
- SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
/* Test BoundBox */
@@ -2558,14 +2558,9 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
}
- Nearest2dUserData nearest2d = {
- .userdata = em,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .use_backface_culling = use_backface_culling,
- };
+ Nearest2dUserData nearest2d;
+ nearest2d_data_init(
+ sod, snapdata->view_proj == VIEW_PROJ_PERSP, use_backface_culling, &nearest2d);
BVHTreeNearest nearest = {
.index = -1,
@@ -2659,9 +2654,9 @@ struct SnapObjUserData {
* \note Duplicate args here are documented at #snapObjectsRay
*/
static void snap_obj_fn(SnapObjectContext *sctx,
- Object *ob,
+ Object *ob_eval,
float obmat[4][4],
- bool use_obedit,
+ eSnapEditType edit_mode_type,
bool use_backface_culling,
bool UNUSED(is_object_active),
void *data)
@@ -2669,41 +2664,36 @@ static void snap_obj_fn(SnapObjectContext *sctx,
struct SnapObjUserData *dt = data;
short retval = 0;
- switch (ob->type) {
+ switch (ob_eval->type) {
case OB_MESH: {
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
- /* Operators only update the editmesh looptris of the original mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
- retval = snapEditMesh(sctx,
- dt->snapdata,
- ob,
- em_orig,
- obmat,
- use_backface_culling,
- dt->dist_px,
- dt->r_loc,
- dt->r_no,
- dt->r_index);
- break;
- }
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
+ bool use_hide;
+ Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
+ if (me_eval == NULL) {
+ /* Operators only update the editmesh looptris of the original mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval));
+ retval = snapEditMesh(sctx,
+ dt->snapdata,
+ ob_eval,
+ em_orig,
+ obmat,
+ use_backface_culling,
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
+ break;
}
- else if (ob->dt == OB_BOUNDBOX) {
+ if (ob_eval->dt == OB_BOUNDBOX) {
/* Do not snap to objects that are in bounding box display mode */
return;
}
retval = snapMesh(sctx,
dt->snapdata,
- ob,
- me,
+ ob_eval,
+ me_eval,
obmat,
+ use_hide,
use_backface_culling,
dt->dist_px,
dt->r_loc,
@@ -2713,21 +2703,28 @@ static void snap_obj_fn(SnapObjectContext *sctx,
}
case OB_ARMATURE:
retval = snapArmature(
- dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
+ dt->snapdata, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CURVE:
- retval = snapCurve(
- dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
+ retval = snapCurve(dt->snapdata,
+ ob_eval,
+ obmat,
+ edit_mode_type == SNAP_GEOM_EDIT,
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (mesh_eval) {
retval |= snapMesh(sctx,
dt->snapdata,
- ob,
+ ob_eval,
mesh_eval,
obmat,
+ false,
use_backface_culling,
dt->dist_px,
dt->r_loc,
@@ -2740,17 +2737,17 @@ static void snap_obj_fn(SnapObjectContext *sctx,
case OB_GPENCIL:
case OB_LAMP:
retval = snap_object_center(
- dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
+ dt->snapdata, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CAMERA:
retval = snapCamera(
- sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
+ sctx, dt->snapdata, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
}
if (retval) {
if (dt->r_ob) {
- *dt->r_ob = ob;
+ *dt->r_ob = ob_eval;
}
if (dt->r_obmat) {
copy_m4_m4(dt->r_obmat, obmat);
@@ -3023,7 +3020,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
short retval = 0;
bool has_hit = false;
- Object *ob = NULL;
+ Object *ob_eval = NULL;
float loc[3];
/* Not all snapping callbacks set the normal,
* initialize this since any hit copies both the `loc` and `no`. */
@@ -3060,7 +3057,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
loc,
no,
&index,
- &ob,
+ &ob_eval,
obmat,
NULL);
@@ -3072,7 +3069,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
copy_v3_v3(r_no, no);
}
if (r_ob) {
- *r_ob = ob;
+ *r_ob = ob_eval;
}
if (r_obmat) {
copy_m4_m4(r_obmat, obmat);
@@ -3108,9 +3105,10 @@ static short transform_snap_context_project_view3d_mixed_impl(
snapdata.has_occlusion_plane = false;
/* By convention we only snap to the original elements of a curve. */
- if (has_hit && ob->type != OB_CURVE) {
+ if (has_hit && ob_eval->type != OB_CURVE) {
/* Compute the new clip_pane but do not add it yet. */
float new_clipplane[4];
+ BLI_ASSERT_UNIT_V3(no);
plane_from_point_normal_v3(new_clipplane, loc, no);
if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
/* The plane is facing the wrong direction. */
@@ -3121,8 +3119,15 @@ static short transform_snap_context_project_view3d_mixed_impl(
new_clipplane[3] += 0.01f;
/* Try to snap only to the polygon. */
- elem_test = snap_mesh_polygon(
- sctx, &snapdata, ob, obmat, params->use_backface_culling, &dist_px_tmp, loc, no, &index);
+ elem_test = snap_mesh_polygon(sctx,
+ &snapdata,
+ ob_eval,
+ obmat,
+ params->use_backface_culling,
+ &dist_px_tmp,
+ loc,
+ no,
+ &index);
if (elem_test) {
elem = elem_test;
}
@@ -3137,7 +3142,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
}
elem_test = snapObjectsRay(
- sctx, depsgraph, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
+ sctx, depsgraph, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob_eval, obmat);
if (elem_test) {
elem = elem_test;
}
@@ -3148,7 +3153,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
snapdata.snap_to_flag = snap_to_flag;
elem = snap_mesh_edge_verts_mixed(sctx,
&snapdata,
- ob,
+ ob_eval,
obmat,
*dist_px,
prev_co,
@@ -3167,7 +3172,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
copy_v3_v3(r_no, no);
}
if (r_ob) {
- *r_ob = ob;
+ *r_ob = ob_eval;
}
if (r_obmat) {
copy_m4_m4(r_obmat, obmat);