UV: warn when unwrapping fails

Report an error when unwrapping can't solve some UV islands,
note that edge-seams may need to be set.

Address T86936
This commit is contained in:
Campbell Barton 2021-03-26 16:27:58 +11:00
parent 8adeab4b0e
commit 64d4e722a0
Notes: blender-bot 2023-02-14 09:19:09 +01:00
Referenced by issue #100733, Unwrap failed on default cube
3 changed files with 83 additions and 27 deletions

View File

@ -4546,7 +4546,10 @@ void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
}
}
void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology_from_uvs)
void param_construct_end(ParamHandle *handle,
ParamBool fill,
ParamBool topology_from_uvs,
int *count_fail)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart = phandle->construction_chart;
@ -4574,6 +4577,9 @@ void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology
if (!topology_from_uvs && nboundaries == 0) {
p_chart_delete(chart);
if (count_fail != NULL) {
*count_fail += 1;
}
continue;
}
@ -4611,12 +4617,11 @@ void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
}
}
void param_lscm_solve(ParamHandle *handle)
void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
int i;
PBool result;
param_assert(phandle->state == PHANDLE_STATE_LSCM);
@ -4624,7 +4629,7 @@ void param_lscm_solve(ParamHandle *handle)
chart = phandle->charts[i];
if (chart->u.lscm.context) {
result = p_chart_lscm_solve(phandle, chart);
const PBool result = p_chart_lscm_solve(phandle, chart);
if (result && !(chart->flag & PCHART_HAS_PINS)) {
p_chart_rotate_minimum_area(chart);
@ -4637,6 +4642,17 @@ void param_lscm_solve(ParamHandle *handle)
if (!result || !(chart->flag & PCHART_HAS_PINS)) {
p_chart_lscm_end(chart);
}
if (result) {
if (count_changed != NULL) {
*count_changed += 1;
}
}
else {
if (count_failed != NULL) {
*count_failed += 1;
}
}
}
}
}

View File

@ -59,7 +59,10 @@ void param_face_add(ParamHandle *handle,
void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys);
void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology_from_uvs);
void param_construct_end(ParamHandle *handle,
ParamBool fill,
ParamBool topology_from_uvs,
int *count_fail);
void param_delete(ParamHandle *handle);
/* Least Squares Conformal Maps:
@ -74,7 +77,7 @@ void param_delete(ParamHandle *handle);
*/
void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
void param_lscm_solve(ParamHandle *handle);
void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed);
void param_lscm_end(ParamHandle *handle);
/* Stretch */

View File

@ -165,6 +165,11 @@ typedef struct UnwrapOptions {
bool correct_aspect;
} UnwrapOptions;
typedef struct UnwrapResultInfo {
int count_changed;
int count_failed;
} UnwrapResultInfo;
static bool uvedit_have_selection(const Scene *scene, BMEditMesh *em, const UnwrapOptions *options)
{
BMFace *efa;
@ -281,7 +286,8 @@ static void construct_param_handle_face_add(ParamHandle *handle,
static ParamHandle *construct_param_handle(const Scene *scene,
Object *ob,
BMesh *bm,
const UnwrapOptions *options)
const UnwrapOptions *options,
UnwrapResultInfo *result_info)
{
ParamHandle *handle;
BMFace *efa;
@ -344,7 +350,10 @@ static ParamHandle *construct_param_handle(const Scene *scene,
}
}
param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
param_construct_end(handle,
options->fill_holes,
options->topology_from_uvs,
result_info ? &result_info->count_failed : NULL);
return handle;
}
@ -355,7 +364,8 @@ static ParamHandle *construct_param_handle(const Scene *scene,
static ParamHandle *construct_param_handle_multi(const Scene *scene,
Object **objects,
const uint objects_len,
const UnwrapOptions *options)
const UnwrapOptions *options,
int *count_fail)
{
ParamHandle *handle;
BMFace *efa;
@ -431,7 +441,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
offset += bm->totface;
}
param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
param_construct_end(handle, options->fill_holes, options->topology_from_uvs, count_fail);
return handle;
}
@ -475,7 +485,8 @@ static void texface_from_original_index(const Scene *scene,
static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
Object *ob,
BMEditMesh *em,
const UnwrapOptions *options)
const UnwrapOptions *options,
UnwrapResultInfo *result_info)
{
ParamHandle *handle;
/* index pointers */
@ -651,7 +662,10 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
}
}
param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
param_construct_end(handle,
options->fill_holes,
options->topology_from_uvs,
result_info ? &result_info->count_failed : NULL);
/* cleanup */
MEM_freeN(faceMap);
@ -707,7 +721,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
ms->blend = RNA_float_get(op->ptr, "blend");
ms->iterations = RNA_int_get(op->ptr, "iterations");
ms->i = 0;
ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options);
ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
ms->lasttime = PIL_check_seconds_timer();
param_stretch_begin(ms->handle);
@ -959,7 +973,7 @@ static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm)
bool ignore_pinned = false;
ParamHandle *handle;
handle = construct_param_handle(scene, ob, bm, &options);
handle = construct_param_handle(scene, ob, bm, &options, NULL);
param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
param_flush(handle);
param_delete(handle);
@ -979,7 +993,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
bool ignore_pinned)
{
ParamHandle *handle;
handle = construct_param_handle_multi(scene, objects, objects_len, options);
handle = construct_param_handle_multi(scene, objects, objects_len, options, NULL);
param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
param_flush(handle);
param_delete(handle);
@ -1087,7 +1101,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options);
ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
param_average(handle, false);
param_flush(handle);
param_delete(handle);
@ -1154,10 +1168,10 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
};
if (use_subsurf) {
handle = construct_param_handle_subsurfed(scene, obedit, em, &options);
handle = construct_param_handle_subsurfed(scene, obedit, em, &options, NULL);
}
else {
handle = construct_param_handle(scene, obedit, em->bm, &options);
handle = construct_param_handle(scene, obedit, em->bm, &options, NULL);
}
param_lscm_begin(handle, PARAM_TRUE, abf);
@ -1182,7 +1196,7 @@ void ED_uvedit_live_unwrap_re_solve(void)
{
if (g_live_unwrap.handles) {
for (int i = 0; i < g_live_unwrap.len; i++) {
param_lscm_solve(g_live_unwrap.handles[i]);
param_lscm_solve(g_live_unwrap.handles[i], NULL, NULL);
param_flush(g_live_unwrap.handles[i]);
}
}
@ -1631,7 +1645,10 @@ static void uv_map_clip_correct(Object *ob, wmOperator *op)
* \{ */
/* Assumes UV Map exists, doesn't run update funcs. */
static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOptions *options)
static void uvedit_unwrap(const Scene *scene,
Object *obedit,
const UnwrapOptions *options,
UnwrapResultInfo *result_info)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
@ -1643,14 +1660,16 @@ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOption
ParamHandle *handle;
if (use_subsurf) {
handle = construct_param_handle_subsurfed(scene, obedit, em, options);
handle = construct_param_handle_subsurfed(scene, obedit, em, options, result_info);
}
else {
handle = construct_param_handle(scene, obedit, em->bm, options);
handle = construct_param_handle(scene, obedit, em->bm, options, result_info);
}
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
param_lscm_solve(handle);
param_lscm_solve(handle,
result_info ? &result_info->count_changed : NULL,
result_info ? &result_info->count_failed : NULL);
param_lscm_end(handle);
param_average(handle, true);
@ -1663,11 +1682,12 @@ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOption
static void uvedit_unwrap_multi(const Scene *scene,
Object **objects,
const int objects_len,
const UnwrapOptions *options)
const UnwrapOptions *options,
UnwrapResultInfo *result_info)
{
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
uvedit_unwrap(scene, obedit, options);
uvedit_unwrap(scene, obedit, options, result_info);
DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
}
@ -1687,7 +1707,7 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
bool rotate = true;
bool ignore_pinned = true;
uvedit_unwrap_multi(scene, objects, objects_len, &options);
uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL);
uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
}
}
@ -1816,11 +1836,28 @@ static int unwrap_exec(bContext *C, wmOperator *op)
}
/* execute unwrap */
uvedit_unwrap_multi(scene, objects, objects_len, &options);
UnwrapResultInfo result_info = {
.count_changed = 0,
.count_failed = 0,
};
uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info);
uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
MEM_freeN(objects);
if (result_info.count_failed == 0 && result_info.count_changed == 0) {
BKE_report(op->reports,
RPT_WARNING,
"Unwrap could not solve any island(s), edge seams may need to be added");
}
else if (result_info.count_failed) {
BKE_reportf(op->reports,
RPT_WARNING,
"Unwrap failed to solve %d of %d island(s), edge seams may need to be added",
result_info.count_failed,
result_info.count_changed + result_info.count_failed);
}
return OPERATOR_FINISHED;
}