Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/uvedit/uvedit_ops.c
| Show First 20 Lines • Show All 4,708 Lines • ▼ Show 20 Lines | do { | ||||
| } | } | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| return true; | return true; | ||||
| } | } | ||||
| static int uv_hide_exec(bContext *C, wmOperator *op) | static int uv_hide_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| SpaceImage *sima = CTX_wm_space_image(C); | SpaceImage *sima = CTX_wm_space_image(C); | ||||
| Object *obedit = CTX_data_edit_object(C); | |||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| const ToolSettings *ts = scene->toolsettings; | const ToolSettings *ts = scene->toolsettings; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | const bool swap = RNA_boolean_get(op->ptr, "unselected"); | ||||
| Image *ima = sima ? sima->image : NULL; | |||||
| const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); | |||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( | |||||
| view_layer, ((View3D *)NULL), &objects_len); | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | |||||
| BMFace *efa; | BMFace *efa; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| MLoopUV *luv; | MLoopUV *luv; | ||||
| const bool swap = RNA_boolean_get(op->ptr, "unselected"); | |||||
| Image *ima = sima ? sima->image : NULL; | |||||
| const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); | |||||
| const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | ||||
| if (ts->uv_flag & UV_SYNC_SELECTION) { | if (ts->uv_flag & UV_SYNC_SELECTION) { | ||||
| if (EDBM_mesh_hide(em, swap)) { | if (EDBM_mesh_hide(em, swap)) { | ||||
| EDBM_update_generic(obedit->data, true, false); | EDBM_update_generic(ob->data, true, false); | ||||
| } | } | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| int hide = 0; | int hide = 0; | ||||
| if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { | if (!uvedit_face_visible_test(scene, ob, ima, efa)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| if (UV_SEL_TEST(luv, !swap)) { | if (UV_SEL_TEST(luv, !swap)) { | ||||
| hide = 1; | hide = 1; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (hide) { | if (hide) { | ||||
| /* note, a special case for edges could be used, | /* note, a special case for edges could be used, | ||||
| * for now edges act like verts and get flushed */ | * for now edges act like verts and get flushed */ | ||||
| if (use_face_center) { | if (use_face_center) { | ||||
| if (em->selectmode == SCE_SELECT_FACE) { | if (em->selectmode == SCE_SELECT_FACE) { | ||||
| /* check that every UV is selected */ | /* check that every UV is selected */ | ||||
| if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { | if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { | ||||
| BM_face_select_set(em->bm, efa, false); | BM_face_select_set(em->bm, efa, false); | ||||
| } | } | ||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | ||||
| } | } | ||||
| else { | else { | ||||
| if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { | if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| if (UV_SEL_TEST(luv, !swap)) { | if (UV_SEL_TEST(luv, !swap)) { | ||||
| BM_vert_select_set(em->bm, l->v, false); | BM_vert_select_set(em->bm, l->v, false); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (!swap) { | if (!swap) { | ||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (em->selectmode == SCE_SELECT_FACE) { | else if (em->selectmode == SCE_SELECT_FACE) { | ||||
| /* check if a UV is de-selected */ | /* check if a UV is de-selected */ | ||||
| if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) { | if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) { | ||||
| BM_face_select_set(em->bm, efa, false); | BM_face_select_set(em->bm, efa, false); | ||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| if (UV_SEL_TEST(luv, !swap)) { | if (UV_SEL_TEST(luv, !swap)) { | ||||
| BM_vert_select_set(em->bm, l->v, false); | BM_vert_select_set(em->bm, l->v, false); | ||||
| if (!swap) { | if (!swap) { | ||||
| luv->flag &= ~MLOOPUV_VERTSEL; | luv->flag &= ~MLOOPUV_VERTSEL; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* flush vertex selection changes */ | /* flush vertex selection changes */ | ||||
| if (em->selectmode != SCE_SELECT_FACE) { | if (em->selectmode != SCE_SELECT_FACE) { | ||||
| EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE); | EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE); | ||||
| } | } | ||||
| BM_select_history_validate(em->bm); | BM_select_history_validate(em->bm); | ||||
| DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); | DEG_id_tag_update(ob->data, ID_RECALC_SELECT); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); | ||||
| } | |||||
| MEM_freeN(objects); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| #undef UV_SEL_TEST | #undef UV_SEL_TEST | ||||
| static void UV_OT_hide(wmOperatorType *ot) | static void UV_OT_hide(wmOperatorType *ot) | ||||
| { | { | ||||
| Show All 14 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Reveal Operator | /** \name Reveal Operator | ||||
| * \{ */ | * \{ */ | ||||
| static int uv_reveal_exec(bContext *C, wmOperator *op) | static int uv_reveal_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| SpaceImage *sima = CTX_wm_space_image(C); | SpaceImage *sima = CTX_wm_space_image(C); | ||||
| Object *obedit = CTX_data_edit_object(C); | |||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| const ToolSettings *ts = scene->toolsettings; | const ToolSettings *ts = scene->toolsettings; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); | |||||
| const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; | |||||
| const bool select = RNA_boolean_get(op->ptr, "select"); | |||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( | |||||
| view_layer, ((View3D *)NULL), &objects_len); | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | |||||
| BMFace *efa; | BMFace *efa; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| MLoopUV *luv; | MLoopUV *luv; | ||||
| const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); | |||||
| const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; | |||||
| const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | ||||
| const bool select = RNA_boolean_get(op->ptr, "select"); | |||||
| /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and | /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and | ||||
| * confuse our checks on selected verts. */ | * confuse our checks on selected verts. */ | ||||
| /* call the mesh function if we are in mesh sync sel */ | /* call the mesh function if we are in mesh sync sel */ | ||||
| if (ts->uv_flag & UV_SYNC_SELECTION) { | if (ts->uv_flag & UV_SYNC_SELECTION) { | ||||
| if (EDBM_mesh_reveal(em, select)) { | if (EDBM_mesh_reveal(em, select)) { | ||||
| EDBM_update_generic(obedit->data, true, false); | EDBM_update_generic(ob->data, true, false); | ||||
| } | } | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| if (use_face_center) { | if (use_face_center) { | ||||
| if (em->selectmode == SCE_SELECT_FACE) { | if (em->selectmode == SCE_SELECT_FACE) { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_disable(efa, BM_ELEM_TAG); | BM_elem_flag_disable(efa, BM_ELEM_TAG); | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | ||||
| } | } | ||||
| /* BM_face_select_set(em->bm, efa, true); */ | /* BM_face_select_set(em->bm, efa, true); */ | ||||
| BM_elem_flag_enable(efa, BM_ELEM_TAG); | BM_elem_flag_enable(efa, BM_ELEM_TAG); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* enable adjacent faces to have disconnected UV selections if sticky is disabled */ | /* enable adjacent faces to have disconnected UV selections if sticky is disabled */ | ||||
| if (!stickymode) { | if (!stickymode) { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_disable(efa, BM_ELEM_TAG); | BM_elem_flag_disable(efa, BM_ELEM_TAG); | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| int totsel = 0; | int totsel = 0; | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| totsel += BM_elem_flag_test(l->v, BM_ELEM_SELECT); | totsel += BM_elem_flag_test(l->v, BM_ELEM_SELECT); | ||||
| } | } | ||||
| if (!totsel) { | if (!totsel) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | ||||
| } | } | ||||
| /* BM_face_select_set(em->bm, efa, true); */ | /* BM_face_select_set(em->bm, efa, true); */ | ||||
| BM_elem_flag_enable(efa, BM_ELEM_TAG); | BM_elem_flag_enable(efa, BM_ELEM_TAG); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_disable(efa, BM_ELEM_TAG); | BM_elem_flag_disable(efa, BM_ELEM_TAG); | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { | if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | ||||
| } | } | ||||
| } | } | ||||
| /* BM_face_select_set(em->bm, efa, true); */ | /* BM_face_select_set(em->bm, efa, true); */ | ||||
| BM_elem_flag_enable(efa, BM_ELEM_TAG); | BM_elem_flag_enable(efa, BM_ELEM_TAG); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (em->selectmode == SCE_SELECT_FACE) { | else if (em->selectmode == SCE_SELECT_FACE) { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_disable(efa, BM_ELEM_TAG); | BM_elem_flag_disable(efa, BM_ELEM_TAG); | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | ||||
| } | } | ||||
| /* BM_face_select_set(em->bm, efa, true); */ | /* BM_face_select_set(em->bm, efa, true); */ | ||||
| BM_elem_flag_enable(efa, BM_ELEM_TAG); | BM_elem_flag_enable(efa, BM_ELEM_TAG); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_disable(efa, BM_ELEM_TAG); | BM_elem_flag_disable(efa, BM_ELEM_TAG); | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { | if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); | ||||
| } | } | ||||
| } | } | ||||
| /* BM_face_select_set(em->bm, efa, true); */ | /* BM_face_select_set(em->bm, efa, true); */ | ||||
| BM_elem_flag_enable(efa, BM_ELEM_TAG); | BM_elem_flag_enable(efa, BM_ELEM_TAG); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* re-select tagged faces */ | /* re-select tagged faces */ | ||||
| BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); | BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); | ||||
| DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); | DEG_id_tag_update(ob->data, ID_RECALC_SELECT); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); | ||||
| } | |||||
| MEM_freeN(objects); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static void UV_OT_reveal(wmOperatorType *ot) | static void UV_OT_reveal(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Reveal Hidden"; | ot->name = "Reveal Hidden"; | ||||
| ▲ Show 20 Lines • Show All 402 Lines • Show Last 20 Lines | |||||