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:
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c123
1 files changed, 77 insertions, 46 deletions
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 58cf82c72d3..de2f96c0f97 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -69,28 +69,43 @@ struct TransCustomData_PartialUpdate {
float prop_size_prev;
};
+/**
+ * \note It's important to order from least to greatest (which updates more data),
+ * since the larger values are used when values change between updates
+ * (which can happen when rotation is enabled with snapping).
+ */
enum ePartialType {
PARTIAL_NONE = -1,
/**
- * Update for all tagged vertices (any kind of deformation).
- * Use as a default since it can be used with any kind of deformation.
- */
- PARTIAL_TYPE_ALL = 0,
- /**
* Update only faces between tagged and non-tagged faces (affine transformations).
* Use when transforming is guaranteed not to change the relative locations of vertices.
*
* This has the advantage that selecting the entire mesh or only isolated elements,
* can skip normal/tessellation updates entirely, so it's worth using when possible.
*/
- PARTIAL_TYPE_GROUP = 1,
-
+ PARTIAL_TYPE_GROUP = 0,
+ /**
+ * Update for all tagged vertices (any kind of deformation).
+ * Use as a default since it can be used with any kind of deformation.
+ */
+ PARTIAL_TYPE_ALL = 1,
};
+
#define PARTIAL_TYPE_MAX 2
+/**
+ * Settings used for a single update,
+ * use for comparison with previous updates.
+ */
+struct PartialTypeState {
+ enum ePartialType for_looptri;
+ enum ePartialType for_normals;
+};
+
struct TransCustomDataMesh {
struct TransCustomDataLayer *cd_layer_correct;
struct TransCustomData_PartialUpdate partial_update[PARTIAL_TYPE_MAX];
+ struct PartialTypeState partial_update_state_prev;
};
static struct TransCustomDataMesh *tc_mesh_customdata_ensure(TransDataContainer *tc)
@@ -102,6 +117,8 @@ static struct TransCustomDataMesh *tc_mesh_customdata_ensure(TransDataContainer
tc->custom.type.data = MEM_callocN(sizeof(struct TransCustomDataMesh), __func__);
tc->custom.type.free_cb = tc_mesh_customdata_free_fn;
tcmd = tc->custom.type.data;
+ tcmd->partial_update_state_prev.for_looptri = PARTIAL_NONE;
+ tcmd->partial_update_state_prev.for_normals = PARTIAL_NONE;
}
return tcmd;
}
@@ -1895,9 +1912,7 @@ static BMPartialUpdate *tc_mesh_partial_ensure(TransInfo *t,
return pupdate->cache;
}
-static void tc_mesh_partial_types_calc(TransInfo *t,
- enum ePartialType *r_partial_for_looptri,
- enum ePartialType *r_partial_for_normals)
+static void tc_mesh_partial_types_calc(TransInfo *t, struct PartialTypeState *r_partial_state)
{
/* Calculate the kind of partial updates which can be performed. */
enum ePartialType partial_for_normals = PARTIAL_NONE;
@@ -1909,6 +1924,10 @@ static void tc_mesh_partial_types_calc(TransInfo *t,
case TFM_TRANSLATION: {
partial_for_looptri = PARTIAL_TYPE_GROUP;
partial_for_normals = PARTIAL_TYPE_GROUP;
+ /* Translation can rotate when snapping to normal. */
+ if (activeSnap(t) && usingSnappingNormal(t) && validSnappingNormal(t)) {
+ partial_for_normals = PARTIAL_TYPE_ALL;
+ }
break;
}
case TFM_ROTATION: {
@@ -1946,53 +1965,65 @@ static void tc_mesh_partial_types_calc(TransInfo *t,
}
}
- *r_partial_for_looptri = partial_for_looptri;
- *r_partial_for_normals = partial_for_normals;
+ r_partial_state->for_looptri = partial_for_looptri;
+ r_partial_state->for_normals = partial_for_normals;
}
static void tc_mesh_partial_update(TransInfo *t,
TransDataContainer *tc,
- enum ePartialType partial_for_looptri,
- enum ePartialType partial_for_normals)
+ const struct PartialTypeState *partial_state)
{
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- /* Matching. */
- if ((partial_for_looptri == PARTIAL_TYPE_ALL) && (partial_for_normals == PARTIAL_TYPE_ALL)) {
+ struct TransCustomDataMesh *tcmd = tc_mesh_customdata_ensure(tc);
+
+ const struct PartialTypeState *partial_state_prev = &tcmd->partial_update_state_prev;
+
+ /* Promote the partial update types based on the previous state
+ * so the values that no longer modified are reset before being left as-is.
+ * Needed for translation which can toggle snap-to-normal during transform. */
+ const enum ePartialType partial_for_looptri = MAX2(partial_state->for_looptri,
+ partial_state_prev->for_looptri);
+ const enum ePartialType partial_for_normals = MAX2(partial_state->for_normals,
+ partial_state_prev->for_normals);
+
+ if ((partial_for_looptri == PARTIAL_TYPE_ALL) && (partial_for_normals == PARTIAL_TYPE_ALL) &&
+ (em->bm->totvert == em->bm->totvertsel)) {
/* The additional cost of generating the partial connectivity data isn't justified
* when all data needs to be updated.
*
* While proportional editing can cause all geometry to need updating with a partial
* selection. It's impractical to calculate this ahead of time. Further, the down side of
* using partial updates when their not needed is negligible. */
- if (em->bm->totvert == em->bm->totvertsel) {
- BKE_editmesh_looptri_and_normals_calc(em);
- return;
- }
- }
-
- /* Not matching. */
- if (partial_for_looptri != PARTIAL_NONE) {
- BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_looptri);
- BKE_editmesh_looptri_calc_with_partial_ex(em,
- bmpinfo,
- &(const struct BMeshCalcTessellation_Params){
- .face_normals = true,
- });
- }
-
- if (partial_for_normals != PARTIAL_NONE) {
- BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_normals);
- /* While not a large difference, take advantage of existing normals where possible. */
- const bool face_normals = !((partial_for_looptri == PARTIAL_TYPE_ALL) ||
- ((partial_for_looptri == PARTIAL_TYPE_GROUP) &&
- (partial_for_normals == PARTIAL_TYPE_GROUP)));
- BM_mesh_normals_update_with_partial_ex(em->bm,
- bmpinfo,
- &(const struct BMeshNormalsUpdate_Params){
- .face_normals = face_normals,
- });
+ BKE_editmesh_looptri_and_normals_calc(em);
}
+ else {
+ if (partial_for_looptri != PARTIAL_NONE) {
+ BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_looptri);
+ BKE_editmesh_looptri_calc_with_partial_ex(em,
+ bmpinfo,
+ &(const struct BMeshCalcTessellation_Params){
+ .face_normals = true,
+ });
+ }
+
+ if (partial_for_normals != PARTIAL_NONE) {
+ BMPartialUpdate *bmpinfo = tc_mesh_partial_ensure(t, tc, partial_for_normals);
+ /* While not a large difference, take advantage of existing normals where possible. */
+ const bool face_normals = !((partial_for_looptri == PARTIAL_TYPE_ALL) ||
+ ((partial_for_looptri == PARTIAL_TYPE_GROUP) &&
+ (partial_for_normals == PARTIAL_TYPE_GROUP)));
+ BM_mesh_normals_update_with_partial_ex(em->bm,
+ bmpinfo,
+ &(const struct BMeshNormalsUpdate_Params){
+ .face_normals = face_normals,
+ });
+ }
+ }
+
+ /* Store the previous requested (not the previous used),
+ * since the values used may have been promoted based on the previous types. */
+ tcmd->partial_update_state_prev = *partial_state;
}
/** \} */
@@ -2059,13 +2090,13 @@ void recalcData_mesh(TransInfo *t)
tc_mesh_customdatacorrect_restore(t);
}
- enum ePartialType partial_for_looptri, partial_for_normals;
- tc_mesh_partial_types_calc(t, &partial_for_looptri, &partial_for_normals);
+ struct PartialTypeState partial_state;
+ tc_mesh_partial_types_calc(t, &partial_state);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
- tc_mesh_partial_update(t, tc, partial_for_looptri, partial_for_normals);
+ tc_mesh_partial_update(t, tc, &partial_state);
}
}
/** \} */