diff options
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_unwrap_ops.c')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_unwrap_ops.c | 406 |
1 files changed, 282 insertions, 124 deletions
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index de5838823d1..c7e0dfd7bc7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -40,6 +40,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -53,12 +54,44 @@ #include "PIL_time.h" #include "ED_mesh.h" +#include "ED_screen.h" #include "ED_uvedit.h" +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "uvedit_intern.h" #include "uvedit_parametrizer.h" -/* Parametrizer */ +static void ED_uvedit_create_uvs(EditMesh *em) +{ +#if 0 + if (em && em->faces.first) + EM_add_data_layer(&em->fdata, CD_MTFACE); + + if (!ED_uvedit_test(obedit)) + return; + + if (G.sima && G.sima->image) /* this is a bit of a kludge, but assume they want the image on their mesh when UVs are added */ + image_changed(G.sima, G.sima->image); + + /* select new UV's */ + if ((G.sima==0 || G.sima->flag & SI_SYNC_UVSEL)==0) { + EditFace *efa; + MTFace *tf; + for(efa=em->faces.first; efa; efa=efa->next) { + tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + simaFaceSel_Set(efa, tf); + } + } +#endif +} + +/****************** Parametrizer Conversion ***************/ + ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel) { ParamHandle *handle; @@ -70,13 +103,14 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, handle = param_construct_begin(); - if ((scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT)==0) { + if((scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT)==0) { efa = EM_get_actFace(em, 1); if (efa) { float aspx = 1.0f, aspy= 1.0f; // XXX MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); // XXX image_final_aspect(tf->tpage, &aspx, &aspy); + // XXX get_space_image_aspect(sima, &aspx, &aspy); if (aspx!=aspy) param_aspect_ratio(handle, aspx, aspy); @@ -159,40 +193,24 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, return handle; } -void unwrap_lscm(Scene *scene, Object *obedit, short seamcut) +/* ******************** unwrap operator **************** */ + +static int unwrap_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - short abf = scene->toolsettings->unwrapper == 1; - short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES; + int method = RNA_enum_get(op->ptr, "method"); + int fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); - /* add uvs if there not here */ - if (!ED_uvedit_test(obedit)) { -#if 0 - if (em && em->faces.first) - EM_add_data_layer(&em->fdata, CD_MTFACE); - - if (!ED_uvedit_test(obedit)) - return; - - if (G.sima && G.sima->image) /* this is a bit of a kludge, but assume they want the image on their mesh when UVs are added */ - image_changed(G.sima, G.sima->image); - - /* select new UV's */ - if ((G.sima==0 || G.sima->flag & SI_SYNC_UVSEL)==0) { - EditFace *efa; - MTFace *tf; - for(efa=em->faces.first; efa; efa=efa->next) { - tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - simaFaceSel_Set(efa, tf); - } - } -#endif - } + /* add uvs if they don't exist yet */ + if(!ED_uvedit_test(obedit)) + ED_uvedit_create_uvs(em); - handle = construct_param_handle(scene, em, 0, fillholes, seamcut == 0); + handle= construct_param_handle(scene, em, 0, fill_holes, 0); - param_lscm_begin(handle, PARAM_FALSE, abf); + param_lscm_begin(handle, PARAM_FALSE, method == 0); param_lscm_solve(handle); param_lscm_end(handle); @@ -202,151 +220,291 @@ void unwrap_lscm(Scene *scene, Object *obedit, short seamcut) param_delete(handle); - if (!seamcut) - ; // XXX BIF_undo_push("UV unwrap"); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + return OPERATOR_FINISHED; } -void minimize_stretch_tface_uv(Scene *scene, Object *obedit) +void UV_OT_unwrap(wmOperatorType *ot) { - EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + static EnumPropertyItem method_items[] = { + {0, "ANGLE_BASED", "Angle Based", ""}, + {1, "CONFORMAL", "Conformal", ""}, + {0, NULL, NULL, NULL}}; + + /* identifiers */ + ot->name= "Unwrap"; + ot->idname= "UV_OT_unwrap"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= unwrap_exec; + ot->poll= ED_operator_uvmap; + + /* properties */ + RNA_def_enum(ot->srna, "method", method_items, 0, "Method", "Unwrapping method. Angle Based usually gives better results than Conformal, while being somewhat slower."); + RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry."); +} + +/* ******************** minimize stretch operator **************** */ + +typedef struct MinStretch { + Scene *scene; + Object *obedit; + EditMesh *em; ParamHandle *handle; + float blend; double lasttime; - short doit = 1, escape = 0, val, blend = 0; - unsigned short event = 0; - short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES; - - if(!ED_uvedit_test(obedit)) return; + int i, iterations; + wmTimer *timer; +} MinStretch; - handle = construct_param_handle(scene, em, 1, fillholes, 1); +static void minimize_stretch_init(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + MinStretch *ms; + int fill_holes= RNA_boolean_get(op->ptr, "fill_holes"); + + ms= MEM_callocN(sizeof(MinStretch), "MinStretch"); + ms->scene= scene; + ms->obedit= obedit; + ms->em= em; + ms->blend= RNA_float_get(op->ptr, "blend"); + ms->iterations= RNA_int_get(op->ptr, "iterations"); + ms->handle= construct_param_handle(scene, em, 1, fill_holes, 1); + ms->lasttime= PIL_check_seconds_timer(); + + param_stretch_begin(ms->handle); + if(ms->blend != 0.0f) + param_stretch_blend(ms->handle, ms->blend); + + op->customdata= ms; +} - lasttime = PIL_check_seconds_timer(); +static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive) +{ + MinStretch *ms= op->customdata; + ScrArea *sa= CTX_wm_area(C); - param_stretch_begin(handle); + param_stretch_blend(ms->handle, ms->blend); + param_stretch_iter(ms->handle); - while (doit) { - param_stretch_iter(handle); + if(interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) { + char str[100]; - while (0) { // XXX qtest()) { - event= 0; // XXX extern_qread(&val); + param_flush(ms->handle); - if (val) { -#if 0 - switch (event) { - case ESCKEY: - escape = 1; - case RETKEY: - case PADENTER: - doit = 0; - break; - case PADPLUSKEY: - case WHEELUPMOUSE: - if (blend < 10) { - blend++; - param_stretch_blend(handle, blend*0.1f); - param_flush(handle); - lasttime = 0.0f; - } - break; - case PADMINUS: - case WHEELDOWNMOUSE: - if (blend > 0) { - blend--; - param_stretch_blend(handle, blend*0.1f); - param_flush(handle); - lasttime = 0.0f; - } - break; - } -#endif - } - else if (0) { // XXX (event == LEFTMOUSE) || (event == RIGHTMOUSE)) { - escape = 0; // XXX (event == RIGHTMOUSE); - doit = 0; - } + if(sa) { + sprintf(str, "Minimize Stretch. Blend %.2f.", ms->blend); + ED_area_headerprint(sa, str); } - - if (!doit) - break; - if (PIL_check_seconds_timer() - lasttime > 0.5) { - char str[100]; + ms->lasttime = PIL_check_seconds_timer(); - param_flush(handle); + DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit); + } +} - sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f); - // XXX headerprint(str); +static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel) +{ + MinStretch *ms= op->customdata; + ScrArea *sa= CTX_wm_area(C); - lasttime = PIL_check_seconds_timer(); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - // XXX if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0); - // XXX else force_draw(0); - } - } + if(sa) + ED_area_headerprint(sa, NULL); + if(ms->timer) + WM_event_remove_window_timer(CTX_wm_window(C), ms->timer); - if (escape) - param_flush_restore(handle); + if(cancel) + param_flush_restore(ms->handle); else - param_flush(handle); + param_flush(ms->handle); - param_stretch_end(handle); + param_stretch_end(ms->handle); + param_delete(ms->handle); - param_delete(handle); + DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit); - // XXX BIF_undo_push("UV stretch minimize"); + MEM_freeN(ms); + op->customdata= NULL; +} - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); +static int minimize_stretch_exec(bContext *C, wmOperator *op) +{ + int i, iterations; + + minimize_stretch_init(C, op); + + iterations= RNA_int_get(op->ptr, "iterations"); + for(i=0; i<iterations; i++) + minimize_stretch_iteration(C, op, 0); + minimize_stretch_exit(C, op, 0); + + return OPERATOR_FINISHED; +} + +static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + MinStretch *ms; + + minimize_stretch_init(C, op); + minimize_stretch_iteration(C, op, 1); + + ms= op->customdata; + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f); + + return OPERATOR_RUNNING_MODAL; +} + +static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + MinStretch *ms= op->customdata; + + switch(event->type) { + case ESCKEY: + case RIGHTMOUSE: + minimize_stretch_exit(C, op, 1); + return OPERATOR_CANCELLED; + case RETKEY: + case PADENTER: + case LEFTMOUSE: + minimize_stretch_exit(C, op, 0); + return OPERATOR_FINISHED; + case PADPLUSKEY: + case WHEELUPMOUSE: + if(ms->blend < 0.95f) { + ms->blend += 0.1f; + ms->lasttime= 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } + break; + case PADMINUS: + case WHEELDOWNMOUSE: + if(ms->blend > 0.05f) { + ms->blend -= 0.1f; + ms->lasttime= 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } + break; + case TIMER: + if(ms->timer == event->customdata) { + double start= PIL_check_seconds_timer(); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + do { + minimize_stretch_iteration(C, op, 1); + } while(PIL_check_seconds_timer() - start < 0.01); + } + break; + } + + if(ms->iterations && ms->i >= ms->iterations) { + minimize_stretch_exit(C, op, 0); + return OPERATOR_FINISHED; + } + + return OPERATOR_RUNNING_MODAL; } -void pack_charts_tface_uv(Scene *scene, Object *obedit) +static int minimize_stretch_cancel(bContext *C, wmOperator *op) { + minimize_stretch_exit(C, op, 1); + + return OPERATOR_CANCELLED; +} + +void UV_OT_minimize_stretch(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Minimize Stretch"; + ot->idname= "UV_OT_minimize_stretch"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= minimize_stretch_exec; + ot->invoke= minimize_stretch_invoke; + ot->modal= minimize_stretch_modal; + ot->cancel= minimize_stretch_cancel; + ot->poll= ED_operator_uvedit; + + /* properties */ + RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry."); + RNA_def_float(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original.", 0.0f, 1.0f); + RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively.", 0, 100); +} + +/* ******************** pack islands operator **************** */ + +static int pack_islands_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - - if(!ED_uvedit_test(obedit)) return; handle = construct_param_handle(scene, em, 1, 0, 1); param_pack(handle); param_flush(handle); param_delete(handle); - - // XXX BIF_undo_push("UV pack islands"); - + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + return OPERATOR_FINISHED; } +void UV_OT_pack_islands(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pack Islands"; + ot->idname= "UV_OT_pack_islands"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= pack_islands_exec; + ot->poll= ED_operator_uvedit; +} + +/* ******************** average islands scale operator **************** */ -void average_charts_tface_uv(Scene *scene, Object *obedit) +static int average_islands_scale_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - - if(!ED_uvedit_test(obedit)) return; - handle = construct_param_handle(scene, em, 1, 0, 1); + handle= construct_param_handle(scene, em, 1, 0, 1); param_average(handle); param_flush(handle); param_delete(handle); - - // XXX BIF_undo_push("UV average island scale"); - + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); + + return OPERATOR_FINISHED; +} - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); +void UV_OT_average_islands_scale(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Average Islands Scale"; + ot->idname= "UV_OT_average_islands_scale"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= average_islands_scale_exec; + ot->poll= ED_operator_uvedit; } -/* LSCM live mode */ +/**************** Live Unwrap *****************/ static ParamHandle *liveHandle = NULL; |