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:
parent
8adeab4b0e
commit
64d4e722a0
Notes:
blender-bot
2023-02-14 09:19:09 +01:00
Referenced by issue #100733, Unwrap failed on default cube
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue