PageRenderTime 94ms CodeModel.GetById 46ms RepoModel.GetById 0ms app.codeStats 1ms

/blender-2.63a/source/blender/editors/uvedit/uvedit_ops.c

#
C | 3696 lines | 2727 code | 688 blank | 281 comment | 585 complexity | 79353908284774c73bb53177d3804c82 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  19. * All rights reserved.
  20. *
  21. * The Original Code is: all of this file.
  22. *
  23. * Contributor(s): Antony Riakiotakis.
  24. *
  25. * ***** END GPL LICENSE BLOCK *****
  26. */
  27. /** \file blender/editors/uvedit/uvedit_ops.c
  28. * \ingroup eduv
  29. */
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <math.h>
  33. #include <string.h>
  34. #include "MEM_guardedalloc.h"
  35. #include "DNA_object_types.h"
  36. #include "DNA_material_types.h"
  37. #include "DNA_mesh_types.h"
  38. #include "DNA_meshdata_types.h"
  39. #include "DNA_node_types.h"
  40. #include "DNA_image_types.h"
  41. #include "DNA_space_types.h"
  42. #include "DNA_scene_types.h"
  43. #include "BLI_math.h"
  44. #include "BLI_blenlib.h"
  45. #include "BLI_array.h"
  46. #include "BLI_utildefines.h"
  47. #include "BKE_context.h"
  48. #include "BKE_customdata.h"
  49. #include "BKE_depsgraph.h"
  50. #include "BKE_image.h"
  51. #include "BKE_library.h"
  52. #include "BKE_main.h"
  53. #include "BKE_material.h"
  54. #include "BKE_mesh.h"
  55. #include "BKE_node.h"
  56. #include "BKE_report.h"
  57. #include "BKE_scene.h"
  58. #include "BKE_tessmesh.h"
  59. #include "ED_image.h"
  60. #include "ED_mesh.h"
  61. #include "ED_node.h"
  62. #include "ED_uvedit.h"
  63. #include "ED_object.h"
  64. #include "ED_screen.h"
  65. #include "ED_transform.h"
  66. #include "RNA_access.h"
  67. #include "RNA_define.h"
  68. #include "WM_api.h"
  69. #include "WM_types.h"
  70. #include "UI_view2d.h"
  71. #include "uvedit_intern.h"
  72. static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int action);
  73. /************************* state testing ************************/
  74. int ED_uvedit_test(Object *obedit)
  75. {
  76. BMEditMesh *em;
  77. int ret;
  78. if (!obedit)
  79. return 0;
  80. if (obedit->type != OB_MESH)
  81. return 0;
  82. em = BMEdit_FromObject(obedit);
  83. ret = EDBM_mtexpoly_check(em);
  84. return ret;
  85. }
  86. static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C)
  87. {
  88. SpaceImage *sima = CTX_wm_space_image(C);
  89. ToolSettings *toolsettings = CTX_data_tool_settings(C);
  90. Object *obedit = CTX_data_edit_object(C);
  91. return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt);
  92. }
  93. static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext * C)
  94. {
  95. Object *ob = CTX_data_active_object(C);
  96. if (ob && ob->type == OB_MESH) {
  97. Mesh *me = ob->data;
  98. if (CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL)
  99. return 1;
  100. }
  101. return 0;
  102. }
  103. /**************************** object active image *****************************/
  104. static int is_image_texture_node(bNode *node)
  105. {
  106. return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT);
  107. }
  108. int ED_object_get_active_image(Object *ob, int mat_nr, Image **ima, ImageUser **iuser, bNode **node_r)
  109. {
  110. Material *ma = give_current_material(ob, mat_nr);
  111. bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
  112. if (node && is_image_texture_node(node)) {
  113. if (ima) *ima = (Image *)node->id;
  114. if (iuser) *iuser = NULL;
  115. if (node_r) *node_r = node;
  116. return TRUE;
  117. }
  118. if (ima) *ima = NULL;
  119. if (iuser) *iuser = NULL;
  120. if (node_r) *node_r = node;
  121. return FALSE;
  122. }
  123. void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima)
  124. {
  125. Material *ma = give_current_material(ob, mat_nr);
  126. bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
  127. if (node && is_image_texture_node(node)) {
  128. node->id = &ima->id;
  129. ED_node_generic_update(bmain, ma->nodetree, node);
  130. }
  131. }
  132. /************************* assign image ************************/
  133. void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *ima, Image *previma)
  134. {
  135. BMEditMesh *em;
  136. BMFace *efa;
  137. BMIter iter;
  138. MTexPoly *tf;
  139. int update = 0;
  140. /* skip assigning these procedural images... */
  141. if (ima && (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE))
  142. return;
  143. /* verify we have a mesh we can work with */
  144. if (!obedit || (obedit->type != OB_MESH))
  145. return;
  146. em = BMEdit_FromObject(obedit);
  147. if (!em || !em->bm->totface) {
  148. return;
  149. }
  150. if (scene_use_new_shading_nodes(scene)) {
  151. /* new shading system, assign image in material */
  152. int sloppy = 1;
  153. BMFace *efa = BM_active_face_get(em->bm, sloppy);
  154. if (efa)
  155. ED_object_assign_active_image(bmain, obedit, efa->mat_nr + 1, ima);
  156. }
  157. else {
  158. /* old shading system, assign image to selected faces */
  159. /* ensure we have a uv map */
  160. if (!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
  161. BM_data_layer_add(em->bm, &em->bm->pdata, CD_MTEXPOLY);
  162. BM_data_layer_add(em->bm, &em->bm->ldata, CD_MLOOPUV);
  163. update = 1;
  164. }
  165. /* now assign to all visible faces */
  166. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  167. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  168. if (uvedit_face_visible_test(scene, previma, efa, tf)) {
  169. if (ima) {
  170. tf->tpage = ima;
  171. if (ima->id.us == 0) id_us_plus(&ima->id);
  172. else id_lib_extern(&ima->id);
  173. }
  174. else {
  175. tf->tpage = NULL;
  176. }
  177. update = 1;
  178. }
  179. }
  180. /* and update depdency graph */
  181. if (update)
  182. DAG_id_tag_update(obedit->data, 0);
  183. }
  184. }
  185. /* dotile - 1, set the tile flag (from the space image)
  186. * 2, set the tile index for the faces. */
  187. static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
  188. {
  189. BMEditMesh *em;
  190. BMFace *efa;
  191. BMIter iter;
  192. MTexPoly *tf;
  193. /* verify if we have something to do */
  194. if (!ima || !ED_uvedit_test(obedit))
  195. return 0;
  196. if ((ima->tpageflag & IMA_TILES) == 0)
  197. return 0;
  198. /* skip assigning these procedural images... */
  199. if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)
  200. return 0;
  201. em = BMEdit_FromObject(obedit);
  202. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  203. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  204. if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT))
  205. tf->tile = curtile; /* set tile index */
  206. }
  207. DAG_id_tag_update(obedit->data, 0);
  208. return 1;
  209. }
  210. /*********************** space conversion *********************/
  211. static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
  212. {
  213. int width, height;
  214. if (sima) {
  215. ED_space_image_size(sima, &width, &height);
  216. }
  217. else {
  218. width = 256;
  219. height = 256;
  220. }
  221. dist[0] = pixeldist / width;
  222. dist[1] = pixeldist / height;
  223. }
  224. /*************** visibility and selection utilities **************/
  225. int uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
  226. {
  227. ToolSettings *ts = scene->toolsettings;
  228. if (ts->uv_flag & UV_SYNC_SELECTION)
  229. return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0);
  230. else
  231. return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
  232. }
  233. int uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf)
  234. {
  235. ToolSettings *ts = scene->toolsettings;
  236. if (ts->uv_flag & UV_SHOW_SAME_IMAGE)
  237. return (tf->tpage == ima) ? uvedit_face_visible_nolocal(scene, efa) : 0;
  238. else
  239. return uvedit_face_visible_nolocal(scene, efa);
  240. }
  241. int uvedit_face_select_test(Scene *scene, BMEditMesh *em, BMFace *efa)
  242. {
  243. ToolSettings *ts = scene->toolsettings;
  244. if (ts->uv_flag & UV_SYNC_SELECTION)
  245. return (BM_elem_flag_test(efa, BM_ELEM_SELECT));
  246. else {
  247. BMLoop *l;
  248. MLoopUV *luv;
  249. BMIter liter;
  250. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  251. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  252. if (!(luv->flag & MLOOPUV_VERTSEL))
  253. return 0;
  254. }
  255. return 1;
  256. }
  257. }
  258. int uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const short do_history)
  259. {
  260. ToolSettings *ts = scene->toolsettings;
  261. if (ts->uv_flag & UV_SYNC_SELECTION) {
  262. BM_face_select_set(em->bm, efa, TRUE);
  263. if (do_history) {
  264. BM_select_history_store(em->bm, (BMElem *)efa);
  265. }
  266. }
  267. else {
  268. BMLoop *l;
  269. MLoopUV *luv;
  270. BMIter liter;
  271. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  272. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  273. luv->flag |= MLOOPUV_VERTSEL;
  274. }
  275. return 1;
  276. }
  277. return 0;
  278. }
  279. int uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa)
  280. {
  281. ToolSettings *ts = scene->toolsettings;
  282. if (ts->uv_flag & UV_SYNC_SELECTION) {
  283. BM_face_select_set(em->bm, efa, FALSE);
  284. }
  285. else {
  286. BMLoop *l;
  287. MLoopUV *luv;
  288. BMIter liter;
  289. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  290. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  291. luv->flag &= ~MLOOPUV_VERTSEL;
  292. }
  293. return 1;
  294. }
  295. return 0;
  296. }
  297. int uvedit_edge_select_test(BMEditMesh *em, Scene *scene, BMLoop *l)
  298. {
  299. ToolSettings *ts = scene->toolsettings;
  300. if (ts->uv_flag & UV_SYNC_SELECTION) {
  301. if (ts->selectmode & SCE_SELECT_FACE) {
  302. return BM_elem_flag_test(l->f, BM_ELEM_SELECT);
  303. }
  304. else if (ts->selectmode == SCE_SELECT_EDGE) {
  305. return BM_elem_flag_test(l->e, BM_ELEM_SELECT);
  306. }
  307. else {
  308. return BM_elem_flag_test(l->v, BM_ELEM_SELECT) &&
  309. BM_elem_flag_test(l->next->v, BM_ELEM_SELECT);
  310. }
  311. }
  312. else {
  313. MLoopUV *luv1, *luv2;
  314. luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  315. luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  316. return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
  317. }
  318. }
  319. void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const short do_history)
  320. {
  321. ToolSettings *ts = scene->toolsettings;
  322. if (ts->uv_flag & UV_SYNC_SELECTION) {
  323. if (ts->selectmode & SCE_SELECT_FACE)
  324. BM_face_select_set(em->bm, l->f, TRUE);
  325. else if (ts->selectmode & SCE_SELECT_EDGE)
  326. BM_edge_select_set(em->bm, l->e, TRUE);
  327. else {
  328. BM_vert_select_set(em->bm, l->e->v1, TRUE);
  329. BM_vert_select_set(em->bm, l->e->v2, TRUE);
  330. }
  331. if (do_history) {
  332. BM_select_history_store(em->bm, (BMElem *)l->e);
  333. }
  334. }
  335. else {
  336. MLoopUV *luv1, *luv2;
  337. luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  338. luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  339. luv1->flag |= MLOOPUV_VERTSEL;
  340. luv2->flag |= MLOOPUV_VERTSEL;
  341. }
  342. }
  343. void uvedit_edge_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l)
  344. {
  345. ToolSettings *ts = scene->toolsettings;
  346. if (ts->uv_flag & UV_SYNC_SELECTION) {
  347. if (ts->selectmode & SCE_SELECT_FACE)
  348. BM_face_select_set(em->bm, l->f, FALSE);
  349. else if (ts->selectmode & SCE_SELECT_EDGE)
  350. BM_edge_select_set(em->bm, l->e, FALSE);
  351. else {
  352. BM_vert_select_set(em->bm, l->e->v1, FALSE);
  353. BM_vert_select_set(em->bm, l->e->v2, FALSE);
  354. }
  355. }
  356. else {
  357. MLoopUV *luv1, *luv2;
  358. luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  359. luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  360. luv1->flag &= ~MLOOPUV_VERTSEL;
  361. luv2->flag &= ~MLOOPUV_VERTSEL;
  362. }
  363. }
  364. int uvedit_uv_select_test(BMEditMesh *em, Scene *scene, BMLoop *l)
  365. {
  366. ToolSettings *ts = scene->toolsettings;
  367. if (ts->uv_flag & UV_SYNC_SELECTION) {
  368. if (ts->selectmode & SCE_SELECT_FACE)
  369. return BM_elem_flag_test(l->f, BM_ELEM_SELECT);
  370. else
  371. return BM_elem_flag_test(l->v, BM_ELEM_SELECT);
  372. }
  373. else {
  374. MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  375. return luv->flag & MLOOPUV_VERTSEL;
  376. }
  377. }
  378. void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const short do_history)
  379. {
  380. ToolSettings *ts = scene->toolsettings;
  381. if (ts->uv_flag & UV_SYNC_SELECTION) {
  382. if (ts->selectmode & SCE_SELECT_FACE)
  383. BM_face_select_set(em->bm, l->f, TRUE);
  384. else
  385. BM_vert_select_set(em->bm, l->v, TRUE);
  386. if (do_history) {
  387. BM_select_history_remove(em->bm, (BMElem *)l->v);
  388. }
  389. }
  390. else {
  391. MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  392. luv->flag |= MLOOPUV_VERTSEL;
  393. }
  394. }
  395. void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l)
  396. {
  397. ToolSettings *ts = scene->toolsettings;
  398. if (ts->uv_flag & UV_SYNC_SELECTION) {
  399. if (ts->selectmode & SCE_SELECT_FACE)
  400. BM_face_select_set(em->bm, l->f, FALSE);
  401. else
  402. BM_vert_select_set(em->bm, l->v, FALSE);
  403. }
  404. else {
  405. MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  406. luv->flag &= ~MLOOPUV_VERTSEL;
  407. }
  408. }
  409. /*********************** live unwrap utilities ***********************/
  410. void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
  411. {
  412. if (sima && (sima->flag & SI_LIVE_UNWRAP)) {
  413. ED_uvedit_live_unwrap_begin(scene, obedit);
  414. ED_uvedit_live_unwrap_re_solve();
  415. ED_uvedit_live_unwrap_end(0);
  416. }
  417. }
  418. /*********************** geometric utilities ***********************/
  419. void poly_uv_center(BMEditMesh *em, BMFace *f, float cent[2])
  420. {
  421. BMLoop *l;
  422. MLoopUV *luv;
  423. BMIter liter;
  424. zero_v2(cent);
  425. BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
  426. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  427. add_v2_v2(cent, luv->uv);
  428. }
  429. mul_v2_fl(cent, 1.0f / (float)f->len);
  430. }
  431. void uv_center(float uv[][2], float cent[2], int quad)
  432. {
  433. if (quad) {
  434. cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0f;
  435. cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0f;
  436. }
  437. else {
  438. cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0f;
  439. cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0f;
  440. }
  441. }
  442. float uv_area(float uv[][2], int quad)
  443. {
  444. if (quad)
  445. return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]);
  446. else
  447. return area_tri_v2(uv[0], uv[1], uv[2]);
  448. }
  449. float poly_uv_area(float uv[][2], int len)
  450. {
  451. //BMESH_TODO: make this not suck
  452. //maybe use scanfill? I dunno.
  453. if (len >= 4)
  454. return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]);
  455. else
  456. return area_tri_v2(uv[0], uv[1], uv[2]);
  457. return 1.0;
  458. }
  459. void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
  460. {
  461. int i;
  462. for (i = 0; i < len; i++) {
  463. uv[i][0] = uv_orig[i][0] * aspx;
  464. uv[i][1] = uv_orig[i][1] * aspy;
  465. }
  466. }
  467. int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
  468. {
  469. BMEditMesh *em = BMEdit_FromObject(obedit);
  470. BMFace *efa;
  471. BMLoop *l;
  472. BMIter iter, liter;
  473. MTexPoly *tf;
  474. MLoopUV *luv;
  475. int sel;
  476. INIT_MINMAX2(min, max);
  477. sel = 0;
  478. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  479. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  480. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  481. continue;
  482. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  483. if (uvedit_uv_select_test(em, scene, l)) {
  484. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  485. DO_MINMAX2(luv->uv, min, max);
  486. sel = 1;
  487. }
  488. }
  489. }
  490. return sel;
  491. }
  492. static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2])
  493. {
  494. BMEditMesh *em = BMEdit_FromObject(obedit);
  495. BMFace *efa;
  496. BMLoop *l;
  497. BMIter iter, liter;
  498. MTexPoly *tf;
  499. MLoopUV *luv;
  500. unsigned int sel = 0;
  501. zero_v2(co);
  502. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  503. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  504. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  505. continue;
  506. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  507. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  508. if (uvedit_uv_select_test(em, scene, l)) {
  509. add_v2_v2(co, luv->uv);
  510. sel++;
  511. }
  512. }
  513. }
  514. mul_v2_fl(co, 1.0f / (float)sel);
  515. return (sel != 0);
  516. }
  517. static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
  518. {
  519. int change = FALSE;
  520. if (mode == V3D_CENTER) { /* bounding box */
  521. float min[2], max[2];
  522. if (ED_uvedit_minmax(scene, ima, obedit, min, max)) {
  523. mid_v2_v2v2(cent, min, max);
  524. change = TRUE;
  525. }
  526. }
  527. else {
  528. if (ED_uvedit_median(scene, ima, obedit, cent)) {
  529. change = TRUE;
  530. }
  531. }
  532. return change;
  533. }
  534. /************************** find nearest ****************************/
  535. void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
  536. {
  537. MTexPoly *tf;
  538. BMFace *efa;
  539. BMLoop *l;
  540. BMIter iter, liter;
  541. MLoopUV *luv, *nextluv;
  542. float mindist, dist;
  543. int i;
  544. mindist = 1e10f;
  545. memset(hit, 0, sizeof(*hit));
  546. BM_mesh_elem_index_ensure(em->bm, BM_VERT);
  547. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  548. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  549. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  550. continue;
  551. i = 0;
  552. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  553. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  554. nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  555. dist = dist_to_line_segment_v2(co, luv->uv, nextluv->uv);
  556. if (dist < mindist) {
  557. hit->tf = tf;
  558. hit->efa = efa;
  559. hit->l = l;
  560. hit->nextl = l->next;
  561. hit->luv = luv;
  562. hit->nextluv = nextluv;
  563. hit->lindex = i;
  564. hit->vert1 = BM_elem_index_get(hit->l->v);
  565. hit->vert2 = BM_elem_index_get(hit->l->next->v);
  566. mindist = dist;
  567. }
  568. i++;
  569. }
  570. }
  571. }
  572. static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
  573. {
  574. MTexPoly *tf;
  575. BMFace *efa;
  576. BMLoop *l;
  577. BMIter iter, liter;
  578. MLoopUV *luv;
  579. float mindist, dist, cent[2];
  580. mindist = 1e10f;
  581. memset(hit, 0, sizeof(*hit));
  582. /*this will fill in hit.vert1 and hit.vert2*/
  583. uv_find_nearest_edge(scene, ima, em, co, hit);
  584. hit->l = hit->nextl = NULL;
  585. hit->luv = hit->nextluv = NULL;
  586. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  587. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  588. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  589. continue;
  590. cent[0] = cent[1] = 0.0f;
  591. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  592. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  593. add_v2_v2(cent, luv->uv);
  594. }
  595. cent[0] /= efa->len;
  596. cent[1] /= efa->len;
  597. dist = fabs(co[0] - cent[0]) + fabs(co[1] - cent[1]);
  598. if (dist < mindist) {
  599. hit->tf = tf;
  600. hit->efa = efa;
  601. mindist = dist;
  602. }
  603. }
  604. }
  605. static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), int id,
  606. float co[2], float uv[2])
  607. {
  608. BMLoop *l;
  609. MLoopUV *luv;
  610. BMIter iter;
  611. float m[3], v1[3], v2[3], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL;
  612. int id1, id2, i;
  613. id1 = (id + efa->len - 1) % efa->len;
  614. id2 = (id + efa->len + 1) % efa->len;
  615. m[0] = co[0] - uv[0];
  616. m[1] = co[1] - uv[1];
  617. i = 0;
  618. BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) {
  619. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  620. if (i == id1)
  621. uv1 = luv->uv;
  622. else if (i == id)
  623. ; /* uv2 = luv->uv; */ /* UNUSED */
  624. else if (i == id2)
  625. uv3 = luv->uv;
  626. i++;
  627. }
  628. sub_v3_v3v3(v1, uv1, uv);
  629. sub_v3_v3v3(v2, uv3, uv);
  630. /* m and v2 on same side of v-v1? */
  631. c1 = v1[0] * m[1] - v1[1] * m[0];
  632. c2 = v1[0] * v2[1] - v1[1] * v2[0];
  633. if (c1 * c2 < 0.0f)
  634. return 0;
  635. /* m and v1 on same side of v-v2? */
  636. c1 = v2[0] * m[1] - v2[1] * m[0];
  637. c2 = v2[0] * v1[1] - v2[1] * v1[0];
  638. return (c1 * c2 >= 0.0f);
  639. }
  640. void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
  641. float co[2], float penalty[2], NearestHit *hit)
  642. {
  643. BMFace *efa;
  644. BMLoop *l;
  645. BMIter iter, liter;
  646. MTexPoly *tf;
  647. MLoopUV *luv;
  648. float mindist, dist;
  649. int i;
  650. /*this will fill in hit.vert1 and hit.vert2*/
  651. uv_find_nearest_edge(scene, ima, em, co, hit);
  652. hit->l = hit->nextl = NULL;
  653. hit->luv = hit->nextluv = NULL;
  654. mindist = 1e10f;
  655. memset(hit, 0, sizeof(*hit));
  656. BM_mesh_elem_index_ensure(em->bm, BM_VERT);
  657. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  658. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  659. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  660. continue;
  661. i = 0;
  662. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  663. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  664. if (penalty && uvedit_uv_select_test(em, scene, l))
  665. dist = fabs(co[0] - luv->uv[0]) + penalty[0] + fabs(co[1] - luv->uv[1]) + penalty[1];
  666. else
  667. dist = fabs(co[0] - luv->uv[0]) + fabs(co[1] - luv->uv[1]);
  668. if (dist <= mindist) {
  669. if (dist == mindist)
  670. if (!nearest_uv_between(em, efa, efa->len, i, co, luv->uv)) {
  671. i++;
  672. continue;
  673. }
  674. mindist = dist;
  675. hit->l = l;
  676. hit->nextl = l->next;
  677. hit->luv = luv;
  678. hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  679. hit->tf = tf;
  680. hit->efa = efa;
  681. hit->lindex = i;
  682. hit->vert1 = BM_elem_index_get(hit->l->v);
  683. }
  684. i++;
  685. }
  686. }
  687. }
  688. int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
  689. {
  690. BMEditMesh *em = BMEdit_FromObject(obedit);
  691. BMFace *efa;
  692. BMLoop *l;
  693. BMIter iter, liter;
  694. MTexPoly *tf;
  695. MLoopUV *luv;
  696. float mindist, dist;
  697. int found = 0;
  698. mindist = 1e10f;
  699. uv[0] = co[0];
  700. uv[1] = co[1];
  701. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  702. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  703. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  704. continue;
  705. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  706. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  707. dist = fabs(co[0] - luv->uv[0]) + fabs(co[1] - luv->uv[1]);
  708. if (dist <= mindist) {
  709. mindist = dist;
  710. uv[0] = luv->uv[0];
  711. uv[1] = luv->uv[1];
  712. found = 1;
  713. }
  714. }
  715. }
  716. return found;
  717. }
  718. UvElement *ED_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
  719. {
  720. UvElement *element;
  721. element = map->vert[BM_elem_index_get(l->v)];
  722. for (; element; element = element->next)
  723. if (element->face == efa)
  724. return element;
  725. return NULL;
  726. }
  727. /*********************** loop select ***********************/
  728. static void select_edgeloop_uv_vertex_loop_flag(UvMapVert *first)
  729. {
  730. UvMapVert *iterv;
  731. int count = 0;
  732. for (iterv = first; iterv; iterv = iterv->next) {
  733. if (iterv->separate && iterv != first)
  734. break;
  735. count++;
  736. }
  737. if (count < 5)
  738. first->flag = 1;
  739. }
  740. static UvMapVert *select_edgeloop_uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a)
  741. {
  742. UvMapVert *iterv, *first;
  743. BMLoop *l;
  744. l = BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, a);
  745. first = EDBM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
  746. for (iterv = first; iterv; iterv = iterv->next) {
  747. if (iterv->separate)
  748. first = iterv;
  749. if (iterv->f == BM_elem_index_get(efa))
  750. return first;
  751. }
  752. return NULL;
  753. }
  754. static int select_edgeloop_uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface)
  755. {
  756. UvMapVert *iterv1, *iterv2;
  757. BMFace *efa;
  758. int tot = 0;
  759. /* count number of faces this edge has */
  760. for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
  761. if (iterv1->separate && iterv1 != first1)
  762. break;
  763. for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
  764. if (iterv2->separate && iterv2 != first2)
  765. break;
  766. if (iterv1->f == iterv2->f) {
  767. /* if face already tagged, don't do this edge */
  768. efa = EDBM_face_at_index(em, iterv1->f);
  769. if (BM_elem_flag_test(efa, BM_ELEM_TAG))
  770. return 0;
  771. tot++;
  772. break;
  773. }
  774. }
  775. }
  776. if (*totface == 0) /* start edge */
  777. *totface = tot;
  778. else if (tot != *totface) /* check for same number of faces as start edge */
  779. return 0;
  780. /* tag the faces */
  781. for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
  782. if (iterv1->separate && iterv1 != first1)
  783. break;
  784. for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
  785. if (iterv2->separate && iterv2 != first2)
  786. break;
  787. if (iterv1->f == iterv2->f) {
  788. efa = EDBM_face_at_index(em, iterv1->f);
  789. BM_elem_flag_enable(efa, BM_ELEM_TAG);
  790. break;
  791. }
  792. }
  793. }
  794. return 1;
  795. }
  796. static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit,
  797. float limit[2], const short extend)
  798. {
  799. BMFace *efa;
  800. BMIter iter, liter;
  801. BMLoop *l;
  802. MTexPoly *tf;
  803. UvVertMap *vmap;
  804. UvMapVert *iterv1, *iterv2;
  805. int a, looking, nverts, starttotf, select;
  806. /* setup */
  807. EDBM_index_arrays_init(em, 0, 0, 1);
  808. vmap = EDBM_uv_vert_map_create(em, 0, 0, limit);
  809. BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
  810. if (!extend) {
  811. select_all_perform(scene, ima, em, SEL_DESELECT);
  812. }
  813. BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, FALSE);
  814. /* set flags for first face and verts */
  815. nverts = hit->efa->len;
  816. iterv1 = select_edgeloop_uv_vertex_map_get(vmap, hit->efa, hit->lindex);
  817. iterv2 = select_edgeloop_uv_vertex_map_get(vmap, hit->efa, (hit->lindex + 1) % nverts);
  818. select_edgeloop_uv_vertex_loop_flag(iterv1);
  819. select_edgeloop_uv_vertex_loop_flag(iterv2);
  820. starttotf = 0;
  821. select_edgeloop_uv_edge_tag_faces(em, iterv1, iterv2, &starttotf);
  822. /* sorry, first edge isn't even ok */
  823. if (iterv1->flag == 0 && iterv2->flag == 0) looking = 0;
  824. else looking = 1;
  825. /* iterate */
  826. while (looking) {
  827. looking = 0;
  828. /* find correct valence edges which are not tagged yet, but connect to tagged one */
  829. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  830. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  831. if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) {
  832. nverts = efa->len;
  833. for (a = 0; a < nverts; a++) {
  834. /* check face not hidden and not tagged */
  835. iterv1 = select_edgeloop_uv_vertex_map_get(vmap, efa, a);
  836. iterv2 = select_edgeloop_uv_vertex_map_get(vmap, efa, (a + 1) % nverts);
  837. if (!iterv1 || !iterv2)
  838. continue;
  839. /* check if vertex is tagged and has right valence */
  840. if (iterv1->flag || iterv2->flag) {
  841. if (select_edgeloop_uv_edge_tag_faces(em, iterv1, iterv2, &starttotf)) {
  842. looking = 1;
  843. BM_elem_flag_enable(efa, BM_ELEM_TAG);
  844. select_edgeloop_uv_vertex_loop_flag(iterv1);
  845. select_edgeloop_uv_vertex_loop_flag(iterv2);
  846. break;
  847. }
  848. }
  849. }
  850. }
  851. }
  852. }
  853. /* do the actual select/deselect */
  854. nverts = hit->efa->len;
  855. iterv1 = select_edgeloop_uv_vertex_map_get(vmap, hit->efa, hit->lindex);
  856. iterv2 = select_edgeloop_uv_vertex_map_get(vmap, hit->efa, (hit->lindex + 1) % nverts);
  857. iterv1->flag = 1;
  858. iterv2->flag = 1;
  859. if (extend) {
  860. if (uvedit_uv_select_test(em, scene, hit->l))
  861. select = 0;
  862. else
  863. select = 1;
  864. }
  865. else
  866. select = 1;
  867. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  868. a = 0;
  869. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  870. iterv1 = select_edgeloop_uv_vertex_map_get(vmap, efa, a);
  871. if (iterv1->flag) {
  872. if (select) uvedit_uv_select_enable(em, scene, l, FALSE);
  873. else uvedit_uv_select_disable(em, scene, l);
  874. }
  875. a++;
  876. }
  877. }
  878. /* cleanup */
  879. EDBM_uv_vert_map_free(vmap);
  880. EDBM_index_arrays_free(em);
  881. return (select) ? 1 : -1;
  882. }
  883. /*********************** linked select ***********************/
  884. static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[2], NearestHit *hit, int extend)
  885. {
  886. BMFace *efa;
  887. BMLoop *l;
  888. BMIter iter, liter;
  889. MTexPoly *tf;
  890. MLoopUV *luv;
  891. UvVertMap *vmap;
  892. UvMapVert *vlist, *iterv, *startv;
  893. int i, stacksize = 0, *stack;
  894. unsigned int a;
  895. char *flag;
  896. EDBM_index_arrays_init(em, 0, 0, 1); /* we can use this too */
  897. vmap = EDBM_uv_vert_map_create(em, 1, 1, limit);
  898. if (vmap == NULL)
  899. return;
  900. stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
  901. flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
  902. if (!hit) {
  903. BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
  904. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  905. if (uvedit_face_visible_test(scene, ima, efa, tf)) {
  906. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  907. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  908. if (luv->flag & MLOOPUV_VERTSEL) {
  909. stack[stacksize] = a;
  910. stacksize++;
  911. flag[a] = 1;
  912. break;
  913. }
  914. }
  915. }
  916. }
  917. }
  918. else {
  919. a = 0;
  920. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  921. if (efa == hit->efa) {
  922. stack[stacksize] = a;
  923. stacksize++;
  924. flag[a] = 1;
  925. break;
  926. }
  927. a++;
  928. }
  929. }
  930. while (stacksize > 0) {
  931. int j;
  932. stacksize--;
  933. a = stack[stacksize];
  934. j = 0;
  935. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  936. if (j == a)
  937. break;
  938. j++;
  939. }
  940. i = 0;
  941. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  942. /* make_uv_vert_map_EM sets verts tmp.l to the indices */
  943. vlist = EDBM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
  944. startv = vlist;
  945. for (iterv = vlist; iterv; iterv = iterv->next) {
  946. if (iterv->separate)
  947. startv = iterv;
  948. if (iterv->f == a)
  949. break;
  950. }
  951. for (iterv = startv; iterv; iterv = iterv->next) {
  952. if ((startv != iterv) && (iterv->separate))
  953. break;
  954. else if (!flag[iterv->f]) {
  955. flag[iterv->f] = 1;
  956. stack[stacksize] = iterv->f;
  957. stacksize++;
  958. }
  959. }
  960. i++;
  961. }
  962. }
  963. if (!extend) {
  964. a = 0;
  965. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  966. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  967. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  968. if (flag[a])
  969. luv->flag |= MLOOPUV_VERTSEL;
  970. else
  971. luv->flag &= ~MLOOPUV_VERTSEL;
  972. }
  973. a++;
  974. }
  975. }
  976. else {
  977. a = 0;
  978. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  979. if (!flag[a]) {
  980. a++;
  981. continue;
  982. }
  983. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  984. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  985. if (luv->flag & MLOOPUV_VERTSEL)
  986. break;
  987. }
  988. if (l)
  989. break;
  990. a++;
  991. }
  992. if (efa) {
  993. a = 0;
  994. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  995. if (!flag[a]) {
  996. a++;
  997. continue;
  998. }
  999. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1000. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1001. luv->flag &= ~MLOOPUV_VERTSEL;
  1002. }
  1003. a++;
  1004. }
  1005. }
  1006. else {
  1007. a = 0;
  1008. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1009. if (!flag[a]) {
  1010. a++;
  1011. continue;
  1012. }
  1013. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1014. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1015. luv->flag |= MLOOPUV_VERTSEL;
  1016. }
  1017. a++;
  1018. }
  1019. }
  1020. }
  1021. MEM_freeN(stack);
  1022. MEM_freeN(flag);
  1023. EDBM_uv_vert_map_free(vmap);
  1024. EDBM_index_arrays_free(em);
  1025. }
  1026. /* WATCH IT: this returns first selected UV,
  1027. * not ideal in many cases since there could be multiple */
  1028. static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVert *eve)
  1029. {
  1030. BMIter liter;
  1031. BMLoop *l;
  1032. BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
  1033. MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
  1034. if (!uvedit_face_visible_test(scene, ima, l->f, tf))
  1035. continue;
  1036. if (uvedit_uv_select_test(em, scene, l)) {
  1037. MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1038. return luv->uv;
  1039. }
  1040. }
  1041. return NULL;
  1042. }
  1043. /* ******************** align operator **************** */
  1044. static void weld_align_uv(bContext *C, int tool)
  1045. {
  1046. SpaceImage *sima;
  1047. Scene *scene;
  1048. Object *obedit;
  1049. Image *ima;
  1050. BMEditMesh *em;
  1051. BMIter iter, liter;
  1052. MTexPoly *tf;
  1053. MLoopUV *luv;
  1054. float cent[2], min[2], max[2];
  1055. scene = CTX_data_scene(C);
  1056. obedit = CTX_data_edit_object(C);
  1057. em = BMEdit_FromObject(obedit);
  1058. ima = CTX_data_edit_image(C);
  1059. sima = CTX_wm_space_image(C);
  1060. INIT_MINMAX2(min, max);
  1061. if (tool == 'a') {
  1062. BMFace *efa;
  1063. BMLoop *l;
  1064. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1065. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1066. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1067. continue;
  1068. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1069. if (uvedit_uv_select_test(em, scene, l)) {
  1070. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1071. DO_MINMAX2(luv->uv, min, max);
  1072. }
  1073. }
  1074. }
  1075. tool = (max[0] - min[0] >= max[1] - min[1]) ? 'y' : 'x';
  1076. }
  1077. uvedit_center(scene, ima, obedit, cent, 0);
  1078. if (tool == 'x' || tool == 'w') {
  1079. BMFace *efa;
  1080. BMLoop *l;
  1081. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1082. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1083. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1084. continue;
  1085. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1086. if (uvedit_uv_select_test(em, scene, l)) {
  1087. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1088. luv->uv[0] = cent[0];
  1089. }
  1090. }
  1091. }
  1092. }
  1093. if (tool == 'y' || tool == 'w') {
  1094. BMFace *efa;
  1095. BMLoop *l;
  1096. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1097. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1098. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1099. continue;
  1100. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1101. if (uvedit_uv_select_test(em, scene, l)) {
  1102. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1103. luv->uv[1] = cent[1];
  1104. }
  1105. }
  1106. }
  1107. }
  1108. if (tool == 's' || tool == 't' || tool == 'u') {
  1109. BMEdge *eed;
  1110. BMLoop *l;
  1111. BMVert *eve;
  1112. BMVert *eve_start;
  1113. BMIter iter, liter, eiter;
  1114. /* clear tag */
  1115. BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
  1116. BM_elem_flag_disable(eve, BM_ELEM_TAG);
  1117. }
  1118. /* tag verts with a selected UV */
  1119. BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
  1120. BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
  1121. tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
  1122. if (!uvedit_face_visible_test(scene, ima, l->f, tf))
  1123. continue;
  1124. if (uvedit_uv_select_test(em, scene, l)) {
  1125. BM_elem_flag_enable(eve, BM_ELEM_TAG);
  1126. break;
  1127. }
  1128. }
  1129. }
  1130. /* flush vertex tags to edges */
  1131. BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
  1132. BM_elem_flag_set(eed, BM_ELEM_TAG, (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) &&
  1133. BM_elem_flag_test(eed->v2, BM_ELEM_TAG)));
  1134. }
  1135. /* find a vertex with only one tagged edge */
  1136. eve_start = NULL;
  1137. BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
  1138. int tot_eed_tag = 0;
  1139. BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
  1140. if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
  1141. tot_eed_tag++;
  1142. }
  1143. }
  1144. if (tot_eed_tag == 1) {
  1145. eve_start = eve;
  1146. break;
  1147. }
  1148. }
  1149. if (eve_start) {
  1150. BMVert **eve_line = NULL;
  1151. BMVert *eve_next = NULL;
  1152. BLI_array_declare(eve_line);
  1153. int i;
  1154. eve = eve_start;
  1155. /* walk over edges, building an array of verts in a line */
  1156. while (eve) {
  1157. BLI_array_append(eve_line, eve);
  1158. /* don't touch again */
  1159. BM_elem_flag_disable(eve, BM_ELEM_TAG);
  1160. eve_next = NULL;
  1161. /* find next eve */
  1162. BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
  1163. if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
  1164. BMVert *eve_other = BM_edge_other_vert(eed, eve);
  1165. if (BM_elem_flag_test(eve_other, BM_ELEM_TAG)) {
  1166. /* this is a tagged vert we didnt walk over yet, step onto it */
  1167. eve_next = eve_other;
  1168. break;
  1169. }
  1170. }
  1171. }
  1172. eve = eve_next;
  1173. }
  1174. /* now we have all verts, make into a line */
  1175. if (BLI_array_count(eve_line) > 2) {
  1176. /* we know the returns from these must be valid */
  1177. float *uv_start = uv_sel_co_from_eve(scene, ima, em, eve_line[0]);
  1178. float *uv_end = uv_sel_co_from_eve(scene, ima, em, eve_line[BLI_array_count(eve_line) - 1]);
  1179. /* For t & u modes */
  1180. float a = 0.0f;
  1181. if (tool == 't') {
  1182. if (uv_start[1] == uv_end[1])
  1183. tool = 's';
  1184. else
  1185. a = (uv_end[0] - uv_start[0]) / (uv_end[1] - uv_start[1]);
  1186. }
  1187. else if (tool == 'u') {
  1188. if (uv_start[0] == uv_end[0])
  1189. tool = 's';
  1190. else
  1191. a = (uv_end[1] - uv_start[1]) / (uv_end[0] - uv_start[0]);
  1192. }
  1193. /* go over all verts except for endpoints */
  1194. for (i = 0; i < BLI_array_count(eve_line); i++) {
  1195. BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
  1196. tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
  1197. if (!uvedit_face_visible_test(scene, ima, l->f, tf))
  1198. continue;
  1199. if (uvedit_uv_select_test(em, scene, l)) {
  1200. MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1201. /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis:
  1202. * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
  1203. * Maybe this should be a BLI func? Or is it already existing?
  1204. * Could use interp_v2_v2v2, but not sure it's worth it here...*/
  1205. if (tool == 't')
  1206. luv->uv[0] = a * (luv->uv[1] - uv_start[1]) + uv_start[0];
  1207. else if (tool == 'u')
  1208. luv->uv[1] = a * (luv->uv[0] - uv_start[0]) + uv_start[1];
  1209. else
  1210. closest_to_line_segment_v2(luv->uv, luv->uv, uv_start, uv_end);
  1211. }
  1212. }
  1213. }
  1214. }
  1215. else {
  1216. /* error - not a line, needs 3+ points */
  1217. }
  1218. if (eve_line) {
  1219. MEM_freeN(eve_line);
  1220. }
  1221. }
  1222. else {
  1223. /* error - cant find an endpoint */
  1224. }
  1225. }
  1226. uvedit_live_unwrap_update(sima, scene, obedit);
  1227. DAG_id_tag_update(obedit->data, 0);
  1228. WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
  1229. }
  1230. static int align_exec(bContext *C, wmOperator *op)
  1231. {
  1232. weld_align_uv(C, RNA_enum_get(op->ptr, "axis"));
  1233. return OPERATOR_FINISHED;
  1234. }
  1235. static void UV_OT_align(wmOperatorType *ot)
  1236. {
  1237. static EnumPropertyItem axis_items[] = {
  1238. {'s', "ALIGN_S", 0, "Straighten", "Align UVs along the line defined by the endpoints"},
  1239. {'t', "ALIGN_T", 0, "Straighten X", "Align UVs along the line defined by the endpoints along the X axis"},
  1240. {'u', "ALIGN_U", 0, "Straighten Y", "Align UVs along the line defined by the endpoints along the Y axis"},
  1241. {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already"},
  1242. {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"},
  1243. {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"},
  1244. {0, NULL, 0, NULL, NULL}};
  1245. /* identifiers */
  1246. ot->name = "Align";
  1247. ot->description = "Align selected UV vertices to an axis";
  1248. ot->idname = "UV_OT_align";
  1249. ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  1250. /* api callbacks */
  1251. ot->exec = align_exec;
  1252. ot->poll = ED_operator_image_active; /* requires space image */;
  1253. /* properties */
  1254. RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on");
  1255. }
  1256. /* ******************** weld operator **************** */
  1257. static int weld_exec(bContext *C, wmOperator *UNUSED(op))
  1258. {
  1259. weld_align_uv(C, 'w');
  1260. return OPERATOR_FINISHED;
  1261. }
  1262. static void UV_OT_weld(wmOperatorType *ot)
  1263. {
  1264. /* identifiers */
  1265. ot->name = "Weld";
  1266. ot->description = "Weld selected UV vertices together";
  1267. ot->idname = "UV_OT_weld";
  1268. ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  1269. /* api callbacks */
  1270. ot->exec = weld_exec;
  1271. ot->poll = ED_operator_uvedit;
  1272. }
  1273. /* ******************** (de)select all operator **************** */
  1274. static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int action)
  1275. {
  1276. ToolSettings *ts = scene->toolsettings;
  1277. BMFace *efa;
  1278. BMLoop *l;
  1279. BMIter iter, liter;
  1280. MTexPoly *tf;
  1281. MLoopUV *luv;
  1282. if (ts->uv_flag & UV_SYNC_SELECTION) {
  1283. switch (action) {
  1284. case SEL_TOGGLE:
  1285. EDBM_select_toggle_all(em);
  1286. break;
  1287. case SEL_SELECT:
  1288. EDBM_flag_enable_all(em, BM_ELEM_SELECT);
  1289. break;
  1290. case SEL_DESELECT:
  1291. EDBM_flag_disable_all(em, BM_ELEM_SELECT);
  1292. break;
  1293. case SEL_INVERT:
  1294. EDBM_select_swap(em);
  1295. EDBM_selectmode_flush(em);
  1296. break;
  1297. }
  1298. }
  1299. else {
  1300. if (action == SEL_TOGGLE) {
  1301. action = SEL_SELECT;
  1302. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1303. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1304. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1305. continue;
  1306. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1307. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1308. if (luv->flag & MLOOPUV_VERTSEL) {
  1309. action = SEL_DESELECT;
  1310. break;
  1311. }
  1312. }
  1313. }
  1314. }
  1315. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1316. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1317. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1318. continue;
  1319. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1320. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1321. switch (action) {
  1322. case SEL_SELECT:
  1323. luv->flag |= MLOOPUV_VERTSEL;
  1324. break;
  1325. case SEL_DESELECT:
  1326. luv->flag &= ~MLOOPUV_VERTSEL;
  1327. break;
  1328. case SEL_INVERT:
  1329. luv->flag ^= MLOOPUV_VERTSEL;
  1330. break;
  1331. }
  1332. }
  1333. }
  1334. }
  1335. }
  1336. static int select_all_exec(bContext *C, wmOperator *op)
  1337. {
  1338. Scene *scene = CTX_data_scene(C);
  1339. Object *obedit = CTX_data_edit_object(C);
  1340. Image *ima = CTX_data_edit_image(C);
  1341. BMEditMesh *em = BMEdit_FromObject(obedit);
  1342. int action = RNA_enum_get(op->ptr, "action");
  1343. select_all_perform(scene, ima, em, action);
  1344. WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
  1345. return OPERATOR_FINISHED;
  1346. }
  1347. static void UV_OT_select_all(wmOperatorType *ot)
  1348. {
  1349. /* identifiers */
  1350. ot->name = "(De)select All";
  1351. ot->description = "Change selection of all UV vertices";
  1352. ot->idname = "UV_OT_select_all";
  1353. ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  1354. /* api callbacks */
  1355. ot->exec = select_all_exec;
  1356. ot->poll = ED_operator_uvedit;
  1357. WM_operator_properties_select_all(ot);
  1358. }
  1359. /* ******************** mouse select operator **************** */
  1360. static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen)
  1361. {
  1362. int i;
  1363. /* this function test if some vertex needs to selected
  1364. * in addition to the existing ones due to sticky select */
  1365. if (sticky == SI_STICKY_DISABLE)
  1366. return 0;
  1367. for (i = 0; i < hitlen; i++) {
  1368. if (hitv[i] == v) {
  1369. if (sticky == SI_STICKY_LOC) {
  1370. if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1])
  1371. return 1;
  1372. }
  1373. else if (sticky == SI_STICKY_VERTEX)
  1374. return 1;
  1375. }
  1376. }
  1377. return 0;
  1378. }
  1379. static int mouse_select(bContext *C, float co[2], int extend, int loop)
  1380. {
  1381. SpaceImage *sima = CTX_wm_space_image(C);
  1382. Scene *scene = CTX_data_scene(C);
  1383. ToolSettings *ts = CTX_data_tool_settings(C);
  1384. Object *obedit = CTX_data_edit_object(C);
  1385. Image *ima = CTX_data_edit_image(C);
  1386. BMEditMesh *em = BMEdit_FromObject(obedit);
  1387. BMFace *efa;
  1388. BMLoop *l;
  1389. BMIter iter, liter;
  1390. MTexPoly *tf;
  1391. MLoopUV *luv;
  1392. NearestHit hit;
  1393. int i, select = 1, selectmode, sticky, sync, *hitv = NULL;
  1394. BLI_array_declare(hitv);
  1395. int flush = 0, hitlen = 0; /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
  1396. float limit[2], **hituv = NULL;
  1397. BLI_array_declare(hituv);
  1398. float penalty[2];
  1399. /* notice 'limit' is the same no matter the zoom level, since this is like
  1400. * remove doubles and could annoying if it joined points when zoomed out.
  1401. * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and
  1402. * shift-selecting can consider an adjacent point close enough to add to
  1403. * the selection rather than de-selecting the closest. */
  1404. uvedit_pixel_to_float(sima, limit, 0.05f);
  1405. uvedit_pixel_to_float(sima, penalty, 5.0f / sima->zoom);
  1406. /* retrieve operation mode */
  1407. if (ts->uv_flag & UV_SYNC_SELECTION) {
  1408. sync = 1;
  1409. if (ts->selectmode & SCE_SELECT_FACE)
  1410. selectmode = UV_SELECT_FACE;
  1411. else if (ts->selectmode & SCE_SELECT_EDGE)
  1412. selectmode = UV_SELECT_EDGE;
  1413. else
  1414. selectmode = UV_SELECT_VERTEX;
  1415. sticky = SI_STICKY_DISABLE;
  1416. }
  1417. else {
  1418. sync = 0;
  1419. selectmode = ts->uv_selectmode;
  1420. sticky = (sima) ? sima->sticky : 1;
  1421. }
  1422. /* find nearest element */
  1423. if (loop) {
  1424. /* find edge */
  1425. uv_find_nearest_edge(scene, ima, em, co, &hit);
  1426. if (hit.efa == NULL) {
  1427. BLI_array_free(hitv);
  1428. BLI_array_free(hituv);
  1429. return OPERATOR_CANCELLED;
  1430. }
  1431. hitlen = 0;
  1432. }
  1433. else if (selectmode == UV_SELECT_VERTEX) {
  1434. /* find vertex */
  1435. uv_find_nearest_vert(scene, ima, em, co, penalty, &hit);
  1436. if (hit.efa == NULL) {
  1437. BLI_array_free(hitv);
  1438. BLI_array_free(hituv);
  1439. return OPERATOR_CANCELLED;
  1440. }
  1441. /* mark 1 vertex as being hit */
  1442. BLI_array_growitems(hitv, hit.efa->len);
  1443. BLI_array_growitems(hituv, hit.efa->len);
  1444. for (i = 0; i < hit.efa->len; i++) {
  1445. hitv[i] = 0xFFFFFFFF;
  1446. }
  1447. hitv[hit.lindex] = hit.vert1;
  1448. hituv[hit.lindex] = hit.luv->uv;
  1449. hitlen = hit.efa->len;
  1450. }
  1451. else if (selectmode == UV_SELECT_EDGE) {
  1452. /* find edge */
  1453. uv_find_nearest_edge(scene, ima, em, co, &hit);
  1454. if (hit.efa == NULL) {
  1455. BLI_array_free(hitv);
  1456. BLI_array_free(hituv);
  1457. return OPERATOR_CANCELLED;
  1458. }
  1459. /* mark 2 edge vertices as being hit */
  1460. BLI_array_growitems(hitv, hit.efa->len);
  1461. BLI_array_growitems(hituv, hit.efa->len);
  1462. fill_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
  1463. hitv[hit.lindex] = hit.vert1;
  1464. hitv[(hit.lindex + 1) % hit.efa->len] = hit.vert2;
  1465. hituv[hit.lindex] = hit.luv->uv;
  1466. hituv[(hit.lindex + 1) % hit.efa->len] = hit.nextluv->uv;
  1467. hitlen = hit.efa->len;
  1468. }
  1469. else if (selectmode == UV_SELECT_FACE) {
  1470. /* find face */
  1471. find_nearest_uv_face(scene, ima, em, co, &hit);
  1472. if (hit.efa == NULL) {
  1473. BLI_array_free(hitv);
  1474. BLI_array_free(hituv);
  1475. return OPERATOR_CANCELLED;
  1476. }
  1477. /* make active */
  1478. BM_active_face_set(em->bm, hit.efa);
  1479. /* mark all face vertices as being hit */
  1480. BLI_array_growitems(hitv, hit.efa->len);
  1481. BLI_array_growitems(hituv, hit.efa->len);
  1482. i = 0;
  1483. BM_ITER_ELEM (l, &liter, hit.efa, BM_LOOPS_OF_FACE) {
  1484. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1485. hituv[i] = luv->uv;
  1486. hitv[i] = BM_elem_index_get(l->v);
  1487. i++;
  1488. }
  1489. hitlen = hit.efa->len;
  1490. }
  1491. else if (selectmode == UV_SELECT_ISLAND) {
  1492. uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
  1493. if (hit.efa == NULL) {
  1494. BLI_array_free(hitv);
  1495. BLI_array_free(hituv);
  1496. return OPERATOR_CANCELLED;
  1497. }
  1498. hitlen = 0;
  1499. }
  1500. else {
  1501. hitlen = 0;
  1502. BLI_array_free(hitv);
  1503. BLI_array_free(hituv);
  1504. return OPERATOR_CANCELLED;
  1505. }
  1506. /* do selection */
  1507. if (loop) {
  1508. flush = select_edgeloop(scene, ima, em, &hit, limit, extend);
  1509. }
  1510. else if (selectmode == UV_SELECT_ISLAND) {
  1511. select_linked(scene, ima, em, limit, &hit, extend);
  1512. }
  1513. else if (extend) {
  1514. if (selectmode == UV_SELECT_VERTEX) {
  1515. /* (de)select uv vertex */
  1516. if (uvedit_uv_select_test(em, scene, hit.l)) {
  1517. uvedit_uv_select_disable(em, scene, hit.l);
  1518. select = 0;
  1519. }
  1520. else {
  1521. uvedit_uv_select_enable(em, scene, hit.l, TRUE);
  1522. select = 1;
  1523. }
  1524. flush = 1;
  1525. }
  1526. else if (selectmode == UV_SELECT_EDGE) {
  1527. /* (de)select edge */
  1528. if (uvedit_edge_select_test(em, scene, hit.l)) {
  1529. uvedit_edge_select_disable(em, scene, hit.l);
  1530. select = 0;
  1531. }
  1532. else {
  1533. uvedit_edge_select_enable(em, scene, hit.l, TRUE);
  1534. select = 1;
  1535. }
  1536. flush = 1;
  1537. }
  1538. else if (selectmode == UV_SELECT_FACE) {
  1539. /* (de)select face */
  1540. if (uvedit_face_select_test(scene, em, hit.efa)) {
  1541. uvedit_face_select_disable(scene, em, hit.efa);
  1542. select = 0;
  1543. }
  1544. else {
  1545. uvedit_face_select_enable(scene, em, hit.efa, TRUE);
  1546. select = 1;
  1547. }
  1548. flush = -1;
  1549. }
  1550. /* de-selecting an edge may deselect a face too - validate */
  1551. if (sync) {
  1552. if (select == FALSE) {
  1553. BM_select_history_validate(em->bm);
  1554. }
  1555. }
  1556. /* (de)select sticky uv nodes */
  1557. if (sticky != SI_STICKY_DISABLE) {
  1558. BM_mesh_elem_index_ensure(em->bm, BM_VERT);
  1559. /* deselect */
  1560. if (select == 0) {
  1561. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1562. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1563. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1564. continue;
  1565. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1566. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1567. if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
  1568. uvedit_uv_select_disable(em, scene, l);
  1569. }
  1570. }
  1571. flush = -1;
  1572. }
  1573. /* select */
  1574. else {
  1575. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1576. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1577. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1578. continue;
  1579. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1580. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1581. if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
  1582. uvedit_uv_select_enable(em, scene, l, FALSE);
  1583. }
  1584. }
  1585. flush = 1;
  1586. }
  1587. }
  1588. }
  1589. else {
  1590. /* deselect all */
  1591. select_all_perform(scene, ima, em, SEL_DESELECT);
  1592. if (selectmode == UV_SELECT_VERTEX) {
  1593. /* select vertex */
  1594. uvedit_uv_select_enable(em, scene, hit.l, TRUE);
  1595. flush = 1;
  1596. }
  1597. else if (selectmode == UV_SELECT_EDGE) {
  1598. /* select edge */
  1599. uvedit_edge_select_enable(em, scene, hit.l, TRUE);
  1600. flush = 1;
  1601. }
  1602. else if (selectmode == UV_SELECT_FACE) {
  1603. /* select face */
  1604. uvedit_face_select_enable(scene, em, hit.efa, TRUE);
  1605. }
  1606. /* select sticky uvs */
  1607. if (sticky != SI_STICKY_DISABLE) {
  1608. BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
  1609. tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  1610. if (!uvedit_face_visible_test(scene, ima, efa, tf))
  1611. continue;
  1612. BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
  1613. if (sticky == SI_STICKY_DISABLE) continue;
  1614. luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  1615. if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
  1616. uvedit_uv_select_enable(em, scene, l, FALSE);
  1617. flush = 1;
  1618. }
  1619. }
  1620. }
  1621. }
  1622. if (sync) {
  1623. /* flush for mesh selection */
  1624. /* before bmesh */
  1625. #if 0
  1626. if (ts->selectmode != SCE_SELECT_FACE) {
  1627. if (flush == 1) EDBM_select_flush(em);
  1628. else if (flush == -1) EDBM_deselect_flush(em);
  1629. }
  1630. #else
  1631. if (flush != 0) {
  1632. if (loop) {
  1633. /* push vertex -> edge selection */
  1634. if (select) {
  1635. EDBM_select_flush(em);

Large files files are truncated, but you can click here to view the full file