Transform: generalized custom-data correction support
Support custom-data correction based on surrounding geometry for all transformation modes of the mesh transform operators. The is the same logic used in Vert and Edge Slide. In order not to change the current default behavior, this property does not affect Vert and Edge Slide modes.
This commit is contained in:
parent
8d3c4aa2d7
commit
4387aff99e
Notes:
blender-bot
2025-02-14 01:40:30 +00:00
Referenced by issue #83161, Crash when moving ruler endpoints and opening or closing the toolshelf Referenced by issue #79581, Polishing Correct Face Attributes Referenced by issue #78695, Bevel improvements for "Correct Face Attributes"
@ -187,6 +187,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
|
||||
bl_context = ".mesh_edit" # dot on purpose (access from topbar)
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_ui_units_x = 12
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@ -198,11 +199,15 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
ob = context.active_object
|
||||
mesh = ob.data
|
||||
|
||||
split = layout.split()
|
||||
|
||||
row = layout.row(align=True, heading="Transform")
|
||||
row.prop(tool_settings, "use_correct_custom_data")
|
||||
|
||||
row = layout.row(heading="Mirror")
|
||||
sub = row.row(align=True)
|
||||
sub.prop(mesh, "use_mirror_x", text="X", toggle=True)
|
||||
|
@ -744,9 +744,21 @@ void BM_loop_interp_from_face(
|
||||
float co[2];
|
||||
int i;
|
||||
|
||||
/* convert the 3d coords into 2d for projection */
|
||||
BLI_assert(BM_face_is_normal_valid(f_src));
|
||||
axis_dominant_v3_to_m3(axis_mat, f_src->no);
|
||||
/* Convert the 3d coords into 2d for projection. */
|
||||
float axis_dominant[3];
|
||||
if (!is_zero_v3(f_src->no)) {
|
||||
BLI_assert(BM_face_is_normal_valid(f_src));
|
||||
copy_v3_v3(axis_dominant, f_src->no);
|
||||
}
|
||||
else {
|
||||
/* Rare case in which all the vertices of the face are aligned.
|
||||
* Get a random axis that is orthogonal to the tangent. */
|
||||
float vec[3];
|
||||
BM_face_calc_tangent_auto(f_src, vec);
|
||||
ortho_v3_v3(axis_dominant, vec);
|
||||
normalize_v3(axis_dominant);
|
||||
}
|
||||
axis_dominant_v3_to_m3(axis_mat, axis_dominant);
|
||||
|
||||
i = 0;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
|
||||
|
@ -526,8 +526,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
|
||||
}
|
||||
|
||||
/* redraw UV editor */
|
||||
if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
|
||||
(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
|
||||
const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ?
|
||||
UVCALC_TRANSFORM_CORRECT_SLIDE :
|
||||
UVCALC_TRANSFORM_CORRECT;
|
||||
|
||||
if ((t->data_type == TC_MESH_VERTS) && (t->settings->uvcalc_flag & uvcalc_correct_flag)) {
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
|
||||
}
|
||||
|
||||
@ -1784,7 +1787,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
|
||||
RNA_property_boolean_set(
|
||||
op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
|
||||
op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
|
||||
void clipUVData(TransInfo *t);
|
||||
|
||||
/* transform_convert_mesh.c */
|
||||
void trans_mesh_customdata_correction_init(TransInfo *t, struct TransDataContainer *tc);
|
||||
void trans_mesh_customdata_correction_init(TransInfo *t);
|
||||
|
||||
/* transform_convert_sequencer.c */
|
||||
int transform_convert_sequencer_get_snap_bound(TransInfo *t);
|
||||
|
@ -1068,18 +1068,29 @@ static void create_trans_vert_customdata_layer(BMVert *v,
|
||||
BLI_ghash_insert(tcld->origverts, v, r_tcld_vert);
|
||||
}
|
||||
|
||||
void trans_mesh_customdata_correction_init(TransInfo *t, TransDataContainer *tc)
|
||||
static void trans_mesh_customdata_correction_init_container(TransInfo *t, TransDataContainer *tc)
|
||||
{
|
||||
if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tc->custom.type.data) {
|
||||
/* Custom data correction has initiated before. */
|
||||
BLI_assert(tc->custom.type.free_cb == trans_mesh_customdata_free_cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ELEM(t->mode,
|
||||
TFM_TRANSLATION,
|
||||
TFM_ROTATION,
|
||||
TFM_RESIZE,
|
||||
TFM_TOSPHERE,
|
||||
TFM_SHEAR,
|
||||
TFM_BEND,
|
||||
TFM_SHRINKFATTEN,
|
||||
TFM_TRACKBALL,
|
||||
TFM_PUSHPULL,
|
||||
TFM_ALIGN)) {
|
||||
/* Currently only modes that change the position of vertices are supported. */
|
||||
return;
|
||||
}
|
||||
|
||||
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
@ -1096,7 +1107,6 @@ void trans_mesh_customdata_correction_init(TransInfo *t, TransDataContainer *tc)
|
||||
return;
|
||||
}
|
||||
|
||||
/* create copies of faces for customdata projection */
|
||||
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
|
||||
|
||||
struct GHash *origfaces = BLI_ghash_ptr_new(__func__);
|
||||
@ -1160,6 +1170,19 @@ void trans_mesh_customdata_correction_init(TransInfo *t, TransDataContainer *tc)
|
||||
tc->custom.type.free_cb = trans_mesh_customdata_free_cb;
|
||||
}
|
||||
|
||||
void trans_mesh_customdata_correction_init(TransInfo *t)
|
||||
{
|
||||
const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ?
|
||||
UVCALC_TRANSFORM_CORRECT_SLIDE :
|
||||
UVCALC_TRANSFORM_CORRECT;
|
||||
|
||||
if (t->settings->uvcalc_flag & uvcalc_correct_flag) {
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
trans_mesh_customdata_correction_init_container(t, tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're sliding the vert, return its original location, if not, the current location is good.
|
||||
*/
|
||||
@ -1375,13 +1398,9 @@ void recalcData_mesh(TransInfo *t)
|
||||
}
|
||||
}
|
||||
|
||||
if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
trans_mesh_customdata_correction_apply(tc, false);
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
trans_mesh_customdata_correction_apply(tc, false);
|
||||
|
||||
DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
|
||||
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
|
||||
EDBM_mesh_normals_update(em);
|
||||
@ -1399,7 +1418,7 @@ void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
|
||||
const bool canceled = (t->state == TRANS_CANCEL);
|
||||
const bool use_automerge = !canceled && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
|
||||
|
||||
if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
|
||||
if (TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.type.data != NULL) {
|
||||
/* Handle multires re-projection, done
|
||||
* on transform completion since it's
|
||||
* really slow -joeedh. */
|
||||
|
@ -375,15 +375,15 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
||||
if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
|
||||
if (RNA_property_is_set(op->ptr, prop)) {
|
||||
if (RNA_property_boolean_get(op->ptr, prop)) {
|
||||
t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
|
||||
t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT_SLIDE;
|
||||
}
|
||||
else {
|
||||
t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
|
||||
t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT_SLIDE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RNA_property_boolean_set(
|
||||
op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
|
||||
op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1271,6 +1271,12 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
|
||||
break;
|
||||
}
|
||||
|
||||
if (t->data_type == TC_MESH_VERTS) {
|
||||
/* Init Custom Data correction.
|
||||
* Ideally this should be called when creating the TransData. */
|
||||
trans_mesh_customdata_correction_init(t);
|
||||
}
|
||||
|
||||
/* TODO(germano): Some of these operations change the `t->mode`.
|
||||
* This can be bad for Redo.
|
||||
* BLI_assert(t->mode == mode); */
|
||||
|
@ -1537,7 +1537,6 @@ void initEdgeSlide_ex(
|
||||
if (sld) {
|
||||
tc->custom.mode.data = sld;
|
||||
tc->custom.mode.free_cb = freeEdgeSlideVerts;
|
||||
trans_mesh_customdata_correction_init(t, tc);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
@ -652,7 +652,6 @@ void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
|
||||
if (sld) {
|
||||
tc->custom.mode.data = sld;
|
||||
tc->custom.mode.free_cb = freeVertSlideVerts;
|
||||
trans_mesh_customdata_correction_init(t, tc);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
@ -327,7 +327,7 @@
|
||||
.doublimit = 0.001, \
|
||||
.vgroup_weight = 1.0f, \
|
||||
.uvcalc_margin = 0.001f, \
|
||||
.uvcalc_flag = UVCALC_TRANSFORM_CORRECT, \
|
||||
.uvcalc_flag = UVCALC_TRANSFORM_CORRECT_SLIDE, \
|
||||
.unwrapper = 1, \
|
||||
.select_thresh = 0.01f, \
|
||||
\
|
||||
|
@ -2235,10 +2235,12 @@ enum {
|
||||
#define UVCALC_FILLHOLES (1 << 0)
|
||||
/** would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */
|
||||
#define UVCALC_NO_ASPECT_CORRECT (1 << 1)
|
||||
/** adjust UV's while transforming to avoid distortion */
|
||||
#define UVCALC_TRANSFORM_CORRECT (1 << 2)
|
||||
/** Adjust UV's while transforming with Vert or Edge Slide. */
|
||||
#define UVCALC_TRANSFORM_CORRECT_SLIDE (1 << 2)
|
||||
/** Use mesh data after subsurf to compute UVs*/
|
||||
#define UVCALC_USESUBSURF (1 << 3)
|
||||
/** adjust UV's while transforming to avoid distortion */
|
||||
#define UVCALC_TRANSFORM_CORRECT (1 << 4)
|
||||
|
||||
/* ToolSettings.uv_flag */
|
||||
#define UV_SYNC_SELECTION 1
|
||||
|
@ -3090,6 +3090,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
||||
prop, "Transform Parents", "Transform the parents, leaving the children in place");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_correct_custom_data", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uvcalc_flag", UVCALC_TRANSFORM_CORRECT);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Correct Face Attributes",
|
||||
"Correct data such as UV coordinates and loop colors when transforming");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "automerge", AUTO_MERGE);
|
||||
RNA_def_property_ui_text(
|
||||
|
Loading…
x
Reference in New Issue
Block a user