diff options
Diffstat (limited to 'source/blender/editors/transform')
8 files changed, 319 insertions, 41 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 68c4f4e76ca..6984dcb18d4 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC transform_convert_mesh_edge.c transform_convert_mesh_skin.c transform_convert_mesh_uv.c + transform_convert_mesh_vert_cdata.c transform_convert_nla.c transform_convert_node.c transform_convert_object.c diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 049d1b6a90e..b01affc7307 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -222,6 +222,7 @@ typedef enum { TC_MESH_EDGES, TC_MESH_SKIN, TC_MESH_UV, + TC_MESH_VERT_CDATA, TC_NLA_DATA, TC_NODE_DATA, TC_OBJECT, diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index bab700560fe..b0148ce508c 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -823,6 +823,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) case TC_GPENCIL: case TC_LATTICE_VERTS: case TC_MBALL_VERTS: + case TC_MESH_VERT_CDATA: case TC_MESH_UV: case TC_MESH_SKIN: case TC_OBJECT_TEXSPACE: @@ -905,6 +906,7 @@ static void init_proportional_edit(TransInfo *t) case TC_MESH_EDGES: case TC_MESH_SKIN: case TC_MESH_UV: + case TC_MESH_VERT_CDATA: case TC_NODE_DATA: case TC_OBJECT: case TC_PARTICLE_VERTS: @@ -939,7 +941,7 @@ static void init_proportional_edit(TransInfo *t) if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { /* Distance has already been set. */ } - else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { + else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN, TC_MESH_VERT_CDATA)) { if (t->flag & T_PROP_CONNECTED) { /* Already calculated by transform_convert_mesh_connectivity_distance. */ } @@ -984,6 +986,7 @@ static void init_TransDataContainers(TransInfo *t, case TC_MESH_EDGES: case TC_MESH_SKIN: case TC_MESH_UV: + case TC_MESH_VERT_CDATA: break; case TC_ACTION_DATA: case TC_GRAPH_EDIT_DATA: @@ -1095,6 +1098,7 @@ static eTFlag flags_from_data_type(eTConvertType data_type) case TC_MBALL_VERTS: case TC_MESH_VERTS: case TC_MESH_SKIN: + case TC_MESH_VERT_CDATA: return T_EDIT | T_POINTS; case TC_MESH_EDGES: return T_EDIT; @@ -1194,6 +1198,9 @@ static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armatur if (t->mode == TFM_SKIN_RESIZE) { convert_type = TC_MESH_SKIN; } + else if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) { + convert_type = TC_MESH_VERT_CDATA; + } else { convert_type = TC_MESH_VERTS; } @@ -1317,6 +1324,9 @@ void createTransData(bContext *C, TransInfo *t) case TC_NLA_DATA: createTransNlaData(C, t); break; + case TC_MESH_VERT_CDATA: + createTransMeshVertCData(t); + break; case TC_NODE_DATA: createTransNodeData(t); break; @@ -1623,6 +1633,9 @@ void recalcData(TransInfo *t) case TC_MESH_UV: recalcData_uv(t); break; + case TC_MESH_VERT_CDATA: + recalcData_mesh_cdata(t); + break; case TC_NLA_DATA: recalcData_nla(t); break; diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index f25a3db3f75..1b7c33e443c 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -252,6 +252,11 @@ void createTransUVs(bContext *C, TransInfo *t); /* helper for recalcData() - for Image Editor transforms */ void recalcData_uv(TransInfo *t); +/* transform_convert_mesh_vert_cdata.c */ + +void createTransMeshVertCData(TransInfo *t); +void recalcData_mesh_cdata(TransInfo *t); + /* transform_convert_nla.c */ void createTransNlaData(bContext *C, TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index c8d943df3fa..de736fad94e 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1408,7 +1408,6 @@ static void VertsToTransData(TransInfo *t, TransDataExtension *tx, BMEditMesh *em, BMVert *eve, - float *bweight, const struct TransIslandData *island_data, const int island_index) { @@ -1449,11 +1448,7 @@ static void VertsToTransData(TransInfo *t, td->ext = NULL; td->val = NULL; td->extra = eve; - if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) { - td->val = bweight; - td->ival = *bweight; - } - else if (t->mode == TFM_SHRINKFATTEN) { + if (t->mode == TFM_SHRINKFATTEN) { td->ext = tx; tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT); } @@ -1589,17 +1584,6 @@ void createTransEditVerts(TransInfo *t) "TransObData ext"); } - int cd_vert_bweight_offset = -1; - int cd_vert_crease_offset = -1; - if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); - cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - } - else if (t->mode == TFM_VERT_CREASE) { - BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_CREASE); - cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); - } - TransData *tob = tc->data; TransDataMirror *td_mirror = tc->data_mirror; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { @@ -1632,15 +1616,9 @@ void createTransEditVerts(TransInfo *t) td_mirror++; } else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - float *bweight = (cd_vert_bweight_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : - (cd_vert_crease_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(eve, cd_vert_crease_offset) : - NULL; - /* Do not use the island center in case we are using islands * only to get axis for snap/rotate to normal... */ - VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index); + VertsToTransData(t, tob, tx, em, eve, &island_data, island_index); if (tx) { tx++; } diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c new file mode 100644 index 00000000000..ff58c2c888b --- /dev/null +++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2001-2002 NaN Holding BV. All rights reserved. */ + +/** \file + * \ingroup edtransform + */ + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_crazyspace.h" +#include "BKE_editmesh.h" +#include "BKE_modifier.h" +#include "BKE_scene.h" + +#include "ED_mesh.h" + +#include "DEG_depsgraph_query.h" + +#include "transform.h" +#include "transform_orientations.h" + +#include "transform_convert.h" + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh #CD_BWEIGHT and #CD_CREASE Transform Creation + * \{ */ + +static float *tc_mesh_cdata_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]; + } + return eve->co; +} + +static void tc_mesh_cdata_transdata_create(TransDataBasic *td, + BMEditMesh *em, + BMVert *eve, + float *weight, + const struct TransIslandData *island_data, + const int island_index) +{ + BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); + + td->loc = weight; + td->iloc[0] = *weight; + + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + td->flag |= TD_SELECTED; + } + + copy_v3_v3(td->center, tc_mesh_cdata_transdata_center(island_data, island_index, eve)); + td->extra = eve; +} + +void createTransMeshVertCData(TransInfo *t) +{ + BLI_assert(ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + Mesh *me = tc->obedit->data; + BMesh *bm = em->bm; + BMVert *eve; + BMIter iter; + float mtx[3][3], smtx[3][3]; + int a; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + + struct TransIslandData island_data = {NULL}; + struct TransMirrorData mirror_data = {NULL}; + struct TransMeshDataCrazySpace crazyspace_data = {NULL}; + + /* Support other objects using PET to adjust these, unless connected is enabled. */ + if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) { + continue; + } + + int cd_offset = -1; + if (t->mode == TFM_BWEIGHT) { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + cd_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + } + else { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_CREASE); + cd_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); + } + + if (cd_offset == -1) { + continue; + } + + int data_len = 0; + if (prop_mode) { + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + data_len++; + } + } + } + else { + data_len = bm->totvertsel; + } + + if (data_len == 0) { + continue; + } + + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know + * the island of the nearest connected vertex. */ + const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + const bool calc_island_center = false; + const bool calc_island_axismtx = false; + + transform_convert_mesh_islands_calc( + em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); + } + + copy_m3_m4(mtx, tc->obedit->obmat); + /* we use a pseudo-inverse so that when one of the axes is scaled to 0, + * matrix inversion still works and we can still moving along the other */ + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); + + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + float *dists = NULL; + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__); + } + transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index); + } + + /* Create TransDataMirror. */ + if (tc->use_mirror_axis_any) { + bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; + bool use_select = (t->flag & T_PROP_EDIT) == 0; + const bool mirror_axis[3] = { + tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; + transform_convert_mesh_mirrordata_calc( + em, use_select, use_topology, mirror_axis, &mirror_data); + + if (mirror_data.vert_map) { + tc->data_mirror_len = mirror_data.mirror_elem_len; + tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), + __func__); + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (mirror_data.vert_map[a].index != -1) { + data_len--; + } + } + } + } + } + + /* Detect CrazySpace [tm]. */ + transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data); + + /* Create TransData. */ + BLI_assert(data_len >= 1); + tc->data_len = data_len; + tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); + + TransData *td = tc->data; + TransDataMirror *td_mirror = tc->data_mirror; + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + continue; + } + + int island_index = -1; + if (island_data.island_vert_map) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + island_index = island_data.island_vert_map[connected_index]; + } + + float *weight = BM_ELEM_CD_GET_VOID_P(eve, cd_offset); + if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) { + tc_mesh_cdata_transdata_create( + (TransDataBasic *)td_mirror, em, eve, weight, &island_data, island_index); + + int elem_index = mirror_data.vert_map[a].index; + BMVert *v_src = BM_vert_at_index(bm, elem_index); + + td_mirror->flag |= mirror_data.vert_map[a].flag; + td_mirror->loc_src = BM_ELEM_CD_GET_VOID_P(v_src, cd_offset); + td_mirror++; + } + else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + tc_mesh_cdata_transdata_create( + (TransDataBasic *)td, em, eve, weight, &island_data, island_index); + + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + createSpaceNormal(td->axismtx, eve->no); + } + else { + /* Setting normals */ + copy_v3_v3(td->axismtx[2], eve->no); + td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] = + td->axismtx[1][1] = td->axismtx[1][2] = 0.0f; + } + + if (prop_mode) { + if (prop_mode & T_PROP_CONNECTED) { + td->dist = dists[a]; + } + else { + td->flag |= TD_NOTCONNECTED; + td->dist = FLT_MAX; + } + } + + /* CrazySpace */ + transform_convert_mesh_crazyspace_transdata_set( + mtx, + smtx, + crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL, + crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ? + crazyspace_data.quats[a] : + NULL, + td); + + td++; + } + } + + transform_convert_mesh_islanddata_free(&island_data); + transform_convert_mesh_mirrordata_free(&mirror_data); + transform_convert_mesh_crazyspace_free(&crazyspace_data); + if (dists) { + MEM_freeN(dists); + } + if (dists_index) { + MEM_freeN(dists_index); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalc Mesh Data + * \{ */ + +static void tc_mesh_cdata_apply_to_mirror(TransInfo *t) +{ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + if (tc->use_mirror_axis_any) { + TransDataMirror *td_mirror = tc->data_mirror; + for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) { + td_mirror->loc[0] = td_mirror->loc_src[0]; + } + } + } +} + +void recalcData_mesh_cdata(TransInfo *t) +{ + bool is_canceling = t->state == TRANS_CANCEL; + /* mirror modifier clipping? */ + if (!is_canceling) { + if (!(t->flag & T_NO_MIRROR)) { + tc_mesh_cdata_apply_to_mirror(t); + } + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BKE_editmesh_looptri_and_normals_calc(em); + } +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 987d8396907..e96e74b596c 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -44,16 +44,11 @@ static void transdata_elem_bevel_weight(const TransInfo *UNUSED(t), TransData *td, const float weight) { - if (td->val == NULL) { + if (td->loc == NULL) { return; } - *td->val = td->ival + weight * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; - } + *td->loc = td->iloc[0] + weight * td->factor; + CLAMP(*td->loc, 0.0f, 1.0f); } static void transdata_elem_bevel_weight_fn(void *__restrict iter_data_v, diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index f1acc2a4c9a..1a3ccf30387 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -44,17 +44,12 @@ static void transdata_elem_crease(const TransInfo *UNUSED(t), TransData *td, const float crease) { - if (td->val == NULL) { + if (td->loc == NULL) { return; } - *td->val = td->ival + crease * td->factor; - if (*td->val < 0.0f) { - *td->val = 0.0f; - } - if (*td->val > 1.0f) { - *td->val = 1.0f; - } + *td->loc = td->iloc[0] + crease * td->factor; + CLAMP(*td->loc, 0.0f, 1.0f); } static void transdata_elem_crease_fn(void *__restrict iter_data_v, |