Blender  V3.3
uvedit_path.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <math.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "BLI_linklist.h"
15 #include "MEM_guardedalloc.h"
16 
17 #include "BLI_ghash.h"
18 #include "BLI_linklist_stack.h"
19 #include "BLI_math.h"
20 #include "BLI_math_vector.h"
21 #include "BLI_utildefines.h"
22 
23 #include "DNA_image_types.h"
24 #include "DNA_mesh_types.h"
25 #include "DNA_meshdata_types.h"
26 #include "DNA_node_types.h"
27 #include "DNA_object_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_space_types.h"
30 
31 #include "BKE_context.h"
32 #include "BKE_customdata.h"
33 #include "BKE_editmesh.h"
34 #include "BKE_layer.h"
35 #include "BKE_mesh.h"
36 #include "BKE_report.h"
37 
38 #include "DEG_depsgraph.h"
39 #include "DEG_depsgraph_query.h"
40 
41 #include "ED_screen.h"
42 #include "ED_transform.h"
43 #include "ED_uvedit.h"
44 
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "UI_view2d.h"
52 
53 #include "intern/bmesh_marking.h"
54 #include "uvedit_intern.h"
55 
56 #include "bmesh_tools.h"
57 
58 /* -------------------------------------------------------------------- */
62 struct PathSelectParams {
64  bool track_active;
66  bool use_face_step;
67  bool use_fill;
69 };
70 
71 struct UserData_UV {
75 };
76 
78 {
80  "use_face_step",
81  false,
82  "Face Stepping",
83  "Traverse connected faces (includes diagonals and edge-rings)");
85  "use_topology_distance",
86  false,
87  "Topology Distance",
88  "Find the minimum number of steps, ignoring spatial distance");
90  "use_fill",
91  false,
92  "Fill Region",
93  "Select all paths between the source/destination elements");
94 
96 }
97 
98 static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params)
99 {
100  op_params->track_active = false;
101  op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
102  op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill");
103  op_params->use_topology_distance = RNA_boolean_get(op->ptr, "use_topology_distance");
105 }
106 
109 /* -------------------------------------------------------------------- */
113 /* callbacks */
114 static bool verttag_filter_cb(BMLoop *l, void *user_data_v)
115 {
116  struct UserData_UV *user_data = user_data_v;
117  return uvedit_face_visible_test(user_data->scene, l->f);
118 }
119 static bool verttag_test_cb(BMLoop *l, void *user_data_v)
120 {
121  /* All connected loops are selected or we return false. */
122  struct UserData_UV *user_data = user_data_v;
123  const Scene *scene = user_data->scene;
124  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
126  BMIter iter;
127  BMLoop *l_iter;
128  BM_ITER_ELEM (l_iter, &iter, l->v, BM_LOOPS_OF_VERT) {
129  if (verttag_filter_cb(l_iter, user_data)) {
130  const MLoopUV *luv_iter = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
131  if (equals_v2v2(luv->uv, luv_iter->uv)) {
133  return false;
134  }
135  }
136  }
137  }
138  return true;
139 }
140 static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v)
141 {
142  struct UserData_UV *user_data = user_data_v;
143  const Scene *scene = user_data->scene;
144  BMEditMesh *em = user_data->em;
145  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
147  BMIter iter;
148  BMLoop *l_iter;
149  BM_ITER_ELEM (l_iter, &iter, l->v, BM_LOOPS_OF_VERT) {
150  if (verttag_filter_cb(l_iter, user_data)) {
151  MLoopUV *luv_iter = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
152  if (equals_v2v2(luv->uv, luv_iter->uv)) {
153  uvedit_uv_select_set(scene, em, l_iter, val, false, cd_loop_uv_offset);
154  }
155  }
156  }
157 }
158 
160  Object *obedit,
161  const struct PathSelectParams *op_params,
162  BMLoop *l_src,
163  BMLoop *l_dst,
164  const float aspect_y,
165  const int cd_loop_uv_offset)
166 {
168  BMesh *bm = em->bm;
169  int flush = 0;
170 
171  struct UserData_UV user_data = {
172  .scene = scene,
173  .em = em,
174  .cd_loop_uv_offset = cd_loop_uv_offset,
175  };
176 
177  const struct BMCalcPathUVParams params = {
178  .use_topology_distance = op_params->use_topology_distance,
179  .use_step_face = op_params->use_face_step,
180  .aspect_y = aspect_y,
181  .cd_loop_uv_offset = cd_loop_uv_offset,
182  };
183 
184  LinkNode *path = NULL;
185  bool is_path_ordered = false;
186 
187  if (l_src != l_dst) {
188  if (op_params->use_fill) {
190  (BMElem *)l_src,
191  (BMElem *)l_dst,
192  params.cd_loop_uv_offset,
194  &user_data);
195  }
196  else {
197  is_path_ordered = true;
199  }
200  }
201 
202  BMLoop *l_dst_last = l_dst;
203 
204  if (path) {
205  /* toggle the flag */
206  bool all_set = true;
207  LinkNode *node = path;
208  do {
209  if (!verttag_test_cb((BMLoop *)node->link, &user_data)) {
210  all_set = false;
211  break;
212  }
213  } while ((node = node->next));
214 
215  int depth = -1;
216  node = path;
217  do {
218  if ((is_path_ordered == false) ||
220  verttag_set_cb((BMLoop *)node->link, !all_set, &user_data);
221  if (is_path_ordered) {
222  l_dst_last = node->link;
223  }
224  }
225  } while ((void)depth++, (node = node->next));
226 
227  BLI_linklist_free(path, NULL);
228  flush = all_set ? -1 : 1;
229  }
230  else {
231  const bool is_act = !verttag_test_cb(l_dst, &user_data);
232  verttag_set_cb(l_dst, is_act, &user_data); /* switch the face option */
233  }
234 
235  if (op_params->track_active) {
236  ED_uvedit_active_vert_loop_set(bm, l_dst_last);
237  }
238  return flush;
239 }
240 
241 /* -------------------------------------------------------------------- */
245 /* callbacks */
246 static bool edgetag_filter_cb(BMLoop *l, void *user_data_v)
247 {
248  struct UserData_UV *user_data = user_data_v;
249  return uvedit_face_visible_test(user_data->scene, l->f);
250 }
251 static bool edgetag_test_cb(BMLoop *l, void *user_data_v)
252 {
253  /* All connected loops (UV) are selected or we return false. */
254  struct UserData_UV *user_data = user_data_v;
255  const Scene *scene = user_data->scene;
256  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
257  BMIter iter;
258  BMLoop *l_iter;
259  BM_ITER_ELEM (l_iter, &iter, l->e, BM_LOOPS_OF_EDGE) {
260  if (edgetag_filter_cb(l_iter, user_data)) {
263  return false;
264  }
265  }
266  }
267  }
268  return true;
269 }
270 static void edgetag_set_cb(BMLoop *l, bool val, void *user_data_v)
271 {
272  struct UserData_UV *user_data = user_data_v;
273  const Scene *scene = user_data->scene;
274  BMEditMesh *em = user_data->em;
275  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
277 }
278 
280  Object *obedit,
281  const struct PathSelectParams *op_params,
282  BMLoop *l_src,
283  BMLoop *l_dst,
284  const float aspect_y,
285  const int cd_loop_uv_offset)
286 {
288  BMesh *bm = em->bm;
289  int flush = 0;
290 
291  struct UserData_UV user_data = {
292  .scene = scene,
293  .em = em,
294  .cd_loop_uv_offset = cd_loop_uv_offset,
295  };
296 
297  const struct BMCalcPathUVParams params = {
298  .use_topology_distance = op_params->use_topology_distance,
299  .use_step_face = op_params->use_face_step,
300  .aspect_y = aspect_y,
301  .cd_loop_uv_offset = cd_loop_uv_offset,
302  };
303 
304  LinkNode *path = NULL;
305  bool is_path_ordered = false;
306 
307  if (l_src != l_dst) {
308  if (op_params->use_fill) {
310  (BMElem *)l_src,
311  (BMElem *)l_dst,
312  params.cd_loop_uv_offset,
314  &user_data);
315  }
316  else {
317  is_path_ordered = true;
319  }
320  }
321 
322  BMLoop *l_dst_last = l_dst;
323 
324  if (path) {
325  /* toggle the flag */
326  bool all_set = true;
327  LinkNode *node = path;
328  do {
329  if (!edgetag_test_cb((BMLoop *)node->link, &user_data)) {
330  all_set = false;
331  break;
332  }
333  } while ((node = node->next));
334 
335  int depth = -1;
336  node = path;
337  do {
338  if ((is_path_ordered == false) ||
340  edgetag_set_cb((BMLoop *)node->link, !all_set, &user_data);
341  if (is_path_ordered) {
342  l_dst_last = node->link;
343  }
344  }
345  } while ((void)depth++, (node = node->next));
346 
347  BLI_linklist_free(path, NULL);
348  flush = all_set ? -1 : 1;
349  }
350  else {
351  const bool is_act = !edgetag_test_cb(l_dst, &user_data);
352  edgetag_set_cb(l_dst, is_act, &user_data); /* switch the face option */
353  }
354 
355  if (op_params->track_active) {
356  ED_uvedit_active_edge_loop_set(bm, l_dst_last);
357  }
358  return flush;
359 }
360 
363 /* -------------------------------------------------------------------- */
367 /* callbacks */
368 static bool facetag_filter_cb(BMFace *f, void *user_data_v)
369 {
370  struct UserData_UV *user_data = user_data_v;
371  return uvedit_face_visible_test(user_data->scene, f);
372 }
373 static bool facetag_test_cb(BMFace *f, void *user_data_v)
374 {
375  /* All connected loops are selected or we return false. */
376  struct UserData_UV *user_data = user_data_v;
377  const Scene *scene = user_data->scene;
378  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
379  BMIter iter;
380  BMLoop *l_iter;
381  BM_ITER_ELEM (l_iter, &iter, f, BM_LOOPS_OF_FACE) {
383  return false;
384  }
385  }
386  return true;
387 }
388 static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
389 {
390  struct UserData_UV *user_data = user_data_v;
391  const Scene *scene = user_data->scene;
392  BMEditMesh *em = user_data->em;
393  const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
395 }
396 
398  Object *obedit,
399  const struct PathSelectParams *op_params,
400  BMFace *f_src,
401  BMFace *f_dst,
402  const float aspect_y,
403  const int cd_loop_uv_offset)
404 {
406  BMesh *bm = em->bm;
407  int flush = 0;
408 
409  struct UserData_UV user_data = {
410  .scene = scene,
411  .em = em,
412  .cd_loop_uv_offset = cd_loop_uv_offset,
413  };
414 
415  const struct BMCalcPathUVParams params = {
416  .use_topology_distance = op_params->use_topology_distance,
417  .use_step_face = op_params->use_face_step,
418  .aspect_y = aspect_y,
419  .cd_loop_uv_offset = cd_loop_uv_offset,
420  };
421 
422  LinkNode *path = NULL;
423  bool is_path_ordered = false;
424 
425  if (f_src != f_dst) {
426  if (op_params->use_fill) {
428  (BMElem *)f_src,
429  (BMElem *)f_dst,
430  params.cd_loop_uv_offset,
432  &user_data);
433  }
434  else {
435  is_path_ordered = true;
437  }
438  }
439 
440  BMFace *f_dst_last = f_dst;
441 
442  if (path) {
443  /* toggle the flag */
444  bool all_set = true;
445  LinkNode *node = path;
446  do {
447  if (!facetag_test_cb((BMFace *)node->link, &user_data)) {
448  all_set = false;
449  break;
450  }
451  } while ((node = node->next));
452 
453  int depth = -1;
454  node = path;
455  do {
456  if ((is_path_ordered == false) ||
458  facetag_set_cb((BMFace *)node->link, !all_set, &user_data);
459  if (is_path_ordered) {
460  f_dst_last = node->link;
461  }
462  }
463  } while ((void)depth++, (node = node->next));
464 
465  BLI_linklist_free(path, NULL);
466  flush = all_set ? -1 : 1;
467  }
468  else {
469  const bool is_act = !facetag_test_cb(f_dst, &user_data);
470  facetag_set_cb(f_dst, is_act, &user_data); /* switch the face option */
471  }
472 
473  if (op_params->track_active) {
474  /* Unlike other types, we can track active without it being selected. */
475  BM_mesh_active_face_set(bm, f_dst_last);
476  }
477  return flush;
478 }
479 
482 /* -------------------------------------------------------------------- */
487 
490  Object *obedit,
491  const struct PathSelectParams *op_params,
492  BMElem *ele_src,
493  BMElem *ele_dst,
494  const float aspect_y,
495  const int cd_loop_uv_offset)
496 {
497  const ToolSettings *ts = scene->toolsettings;
498  const char uv_selectmode = ED_uvedit_select_mode_get(scene);
499  bool ok = false;
500  int flush = 0;
501 
502  if (ELEM(NULL, ele_src, ele_dst) || (ele_src->head.htype != ele_dst->head.htype)) {
503  /* pass */
504  }
505  else if (ele_src->head.htype == BM_FACE) {
507  obedit,
508  op_params,
509  (BMFace *)ele_src,
510  (BMFace *)ele_dst,
511  aspect_y,
513  ok = true;
514  }
515  else if (ele_src->head.htype == BM_LOOP) {
516  if (uv_selectmode & UV_SELECT_EDGE) {
518  obedit,
519  op_params,
520  (BMLoop *)ele_src,
521  (BMLoop *)ele_dst,
522  aspect_y,
524  }
525  else {
527  obedit,
528  op_params,
529  (BMLoop *)ele_src,
530  (BMLoop *)ele_dst,
531  aspect_y,
533  }
534  ok = true;
535  }
536 
537  if (ok) {
538  if (flush != 0) {
539  const bool select = (flush == 1);
540  BMEditMesh *em = BKE_editmesh_from_object(obedit);
541  if (ts->uv_flag & UV_SYNC_SELECTION) {
543  }
544  else {
546  }
547  }
548 
549  if (ts->uv_flag & UV_SYNC_SELECTION) {
551  }
552  else {
553  Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
555  }
556  /* Only for region redraw. */
558  }
559 
560  return ok;
561 }
562 
564 {
566  const ToolSettings *ts = scene->toolsettings;
567  const char uv_selectmode = ED_uvedit_select_mode_get(scene);
568 
569  /* We could support this, it needs further testing. */
570  if (RNA_struct_property_is_set(op->ptr, "index")) {
571  return uv_shortest_path_pick_exec(C, op);
572  }
573 
574  struct PathSelectParams op_params;
575  path_select_params_from_op(op, &op_params);
576 
577  /* Set false if we support edge tagging. */
578  op_params.track_active = true;
579 
581 
582  float co[2];
583 
584  const ARegion *region = CTX_wm_region(C);
585 
586  Object *obedit = CTX_data_edit_object(C);
587  BMEditMesh *em = BKE_editmesh_from_object(obedit);
588  BMesh *bm = em->bm;
589  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
590 
591  float aspect_y;
592  {
593  float aspx, aspy;
594  ED_uvedit_get_aspect(obedit, &aspx, &aspy);
595  aspect_y = aspx / aspy;
596  }
597 
598  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
599 
600  BMElem *ele_src = NULL, *ele_dst = NULL;
601 
602  if (uv_selectmode == UV_SELECT_FACE) {
603  UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
604  if (!uv_find_nearest_face(scene, obedit, co, &hit)) {
605  return OPERATOR_CANCELLED;
606  }
607 
608  BMFace *f_src = BM_mesh_active_face_get(bm, false, false);
609  /* Check selection? */
610 
611  ele_src = (BMElem *)f_src;
612  ele_dst = (BMElem *)hit.efa;
613  }
614 
615  else if (uv_selectmode & UV_SELECT_EDGE) {
616  UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
617  if (!uv_find_nearest_edge(scene, obedit, co, 0.0f, &hit)) {
618  return OPERATOR_CANCELLED;
619  }
620 
621  BMLoop *l_src = NULL;
622  if (ts->uv_flag & UV_SYNC_SELECTION) {
624  if (e_src != NULL) {
625  l_src = uv_find_nearest_loop_from_edge(scene, obedit, e_src, co);
626  }
627  }
628  else {
630  if (l_src != NULL) {
631  if ((!uvedit_uv_select_test(scene, l_src, cd_loop_uv_offset)) &&
632  (!uvedit_uv_select_test(scene, l_src->next, cd_loop_uv_offset))) {
633  l_src = NULL;
634  }
635  ele_src = (BMElem *)l_src;
636  }
637  }
638  ele_src = (BMElem *)l_src;
639  ele_dst = (BMElem *)hit.l;
640  }
641  else {
642  UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
643  if (!uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit)) {
644  return OPERATOR_CANCELLED;
645  }
646 
647  BMLoop *l_src = NULL;
648  if (ts->uv_flag & UV_SYNC_SELECTION) {
650  if (v_src != NULL) {
651  l_src = uv_find_nearest_loop_from_vert(scene, obedit, v_src, co);
652  }
653  }
654  else {
656  if (l_src != NULL) {
657  if (!uvedit_uv_select_test(scene, l_src, cd_loop_uv_offset)) {
658  l_src = NULL;
659  }
660  }
661  }
662  ele_src = (BMElem *)l_src;
663  ele_dst = (BMElem *)hit.l;
664  }
665 
666  if (ele_src == NULL || ele_dst == NULL) {
667  return OPERATOR_CANCELLED;
668  }
669 
671  scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
672 
673  /* To support redo. */
674  int index;
675  if (uv_selectmode & UV_SELECT_FACE) {
677  index = BM_elem_index_get(ele_dst);
678  }
679  else if (uv_selectmode & UV_SELECT_EDGE) {
681  index = BM_elem_index_get(ele_dst);
682  }
683  else {
685  index = BM_elem_index_get(ele_dst);
686  }
687  RNA_int_set(op->ptr, "index", index);
688 
689  return OPERATOR_FINISHED;
690 }
691 
693 {
696  const char uv_selectmode = ED_uvedit_select_mode_get(scene);
697  Object *obedit = CTX_data_edit_object(C);
698  BMEditMesh *em = BKE_editmesh_from_object(obedit);
699  BMesh *bm = em->bm;
700  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
701 
702  float aspect_y;
703  {
704  float aspx, aspy;
705  ED_uvedit_get_aspect(obedit, &aspx, &aspy);
706  aspect_y = aspx / aspy;
707  }
708 
709  const int index = RNA_int_get(op->ptr, "index");
710 
711  BMElem *ele_src, *ele_dst;
712 
713  if (uv_selectmode & UV_SELECT_FACE) {
714  if (index < 0 || index >= bm->totface) {
715  return OPERATOR_CANCELLED;
716  }
717  if (!(ele_src = (BMElem *)BM_mesh_active_face_get(bm, false, false)) ||
718  !(ele_dst = (BMElem *)BM_face_at_index_find_or_table(bm, index))) {
719  return OPERATOR_CANCELLED;
720  }
721  }
722  else if (uv_selectmode & UV_SELECT_EDGE) {
723  if (index < 0 || index >= bm->totloop) {
724  return OPERATOR_CANCELLED;
725  }
726  if (!(ele_src = (BMElem *)ED_uvedit_active_edge_loop_get(bm)) ||
727  !(ele_dst = (BMElem *)BM_loop_at_index_find(bm, index))) {
728  return OPERATOR_CANCELLED;
729  }
730  }
731  else {
732  if (index < 0 || index >= bm->totloop) {
733  return OPERATOR_CANCELLED;
734  }
735  if (!(ele_src = (BMElem *)ED_uvedit_active_vert_loop_get(bm)) ||
736  !(ele_dst = (BMElem *)BM_loop_at_index_find(bm, index))) {
737  return OPERATOR_CANCELLED;
738  }
739  }
740 
741  struct PathSelectParams op_params;
742  path_select_params_from_op(op, &op_params);
743  op_params.track_active = true;
744 
746  scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset)) {
747  return OPERATOR_CANCELLED;
748  }
749 
750  return OPERATOR_FINISHED;
751 }
752 
754 {
755  PropertyRNA *prop;
756 
757  /* identifiers */
758  ot->name = "Pick Shortest Path";
759  ot->idname = "UV_OT_shortest_path_pick";
760  ot->description = "Select shortest path between two selections";
761 
762  /* api callbacks */
766 
767  /* flags */
769 
770  /* properties */
772 
773  /* use for redo */
774  prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
776 }
777 
780 /* -------------------------------------------------------------------- */
785 {
788  const char uv_selectmode = ED_uvedit_select_mode_get(scene);
789  bool found_valid_elements = false;
790 
791  float aspect_y;
792  {
793  Object *obedit = CTX_data_edit_object(C);
794  float aspx, aspy;
795  ED_uvedit_get_aspect(obedit, &aspx, &aspy);
796  aspect_y = aspx / aspy;
797  }
798 
799  ViewLayer *view_layer = CTX_data_view_layer(C);
800  uint objects_len = 0;
802  view_layer, CTX_wm_view3d(C), &objects_len);
803  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
804  Object *obedit = objects[ob_index];
805  BMEditMesh *em = BKE_editmesh_from_object(obedit);
806  BMesh *bm = em->bm;
807  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
808  BMElem *ele_src = NULL, *ele_dst = NULL;
809 
810  /* Find 2x elements. */
811  {
812  BMElem **ele_array = NULL;
813  int ele_array_len = 0;
814  if (uv_selectmode & UV_SELECT_FACE) {
815  ele_array = (BMElem **)ED_uvedit_selected_faces(scene, bm, 3, &ele_array_len);
816  }
817  else if (uv_selectmode & UV_SELECT_EDGE) {
818  ele_array = (BMElem **)ED_uvedit_selected_edges(scene, bm, 3, &ele_array_len);
819  }
820  else {
821  ele_array = (BMElem **)ED_uvedit_selected_verts(scene, bm, 3, &ele_array_len);
822  }
823 
824  if (ele_array_len == 2) {
825  ele_src = ele_array[0];
826  ele_dst = ele_array[1];
827  }
828  MEM_freeN(ele_array);
829  }
830 
831  if (ele_src && ele_dst) {
832  struct PathSelectParams op_params;
833  path_select_params_from_op(op, &op_params);
834 
836  scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
837 
838  found_valid_elements = true;
839  }
840  }
841  MEM_freeN(objects);
842 
843  if (!found_valid_elements) {
844  BKE_report(
845  op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected");
846  return OPERATOR_CANCELLED;
847  }
848 
849  return OPERATOR_FINISHED;
850 }
851 
853 {
854  /* identifiers */
855  ot->name = "Select Shortest Path";
856  ot->idname = "UV_OT_shortest_path_select";
857  ot->description = "Selected shortest path between two vertices/edges/faces";
858 
859  /* api callbacks */
862 
863  /* flags */
865 
866  /* properties */
868 }
869 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const struct CustomData *data, int type)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:542
void BKE_mesh_batch_cache_dirty_tag(struct Mesh *me, eMeshBatchDirtyMode mode)
@ BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ CD_MLOOPUV
Object is a sort of wrapper for general info.
#define UV_SELECT_EDGE
#define UV_SELECT_FACE
#define UV_SYNC_SELECTION
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_operator_uvedit_space_image(struct bContext *C)
Definition: screen_ops.c:564
void ED_uvedit_select_sync_flush(const struct ToolSettings *ts, struct BMEditMesh *em, bool select)
struct BMLoop * ED_uvedit_active_edge_loop_get(struct BMesh *bm)
bool uvedit_uv_select_test(const struct Scene *scene, struct BMLoop *l, int cd_loop_uv_offset)
void ED_uvedit_get_aspect(struct Object *obedit, float *r_aspx, float *r_aspy)
void uvedit_face_select_set_with_sticky(const struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, bool select, bool do_history, int cd_loop_uv_offset)
void ED_uvedit_active_vert_loop_set(struct BMesh *bm, struct BMLoop *l)
Definition: uvedit_select.c:98
struct BMLoop ** ED_uvedit_selected_verts(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_verts_len)
void uvedit_edge_select_set_with_sticky(const struct Scene *scene, struct BMEditMesh *em, struct BMLoop *l, bool select, bool do_history, uint cd_loop_uv_offset)
char ED_uvedit_select_mode_get(const struct Scene *scene)
struct BMLoop * ED_uvedit_active_vert_loop_get(struct BMesh *bm)
bool uvedit_edge_select_test(const struct Scene *scene, struct BMLoop *l, int cd_loop_uv_offset)
void ED_uvedit_active_edge_loop_set(struct BMesh *bm, struct BMLoop *l)
struct BMFace ** ED_uvedit_selected_faces(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_faces_len)
bool uvedit_face_visible_test(const struct Scene *scene, struct BMFace *efa)
void ED_uvedit_selectmode_flush(const struct Scene *scene, struct BMEditMesh *em)
UV Select Mode Flush.
void uvedit_uv_select_set(const struct Scene *scene, struct BMEditMesh *em, struct BMLoop *l, bool select, bool do_history, int cd_loop_uv_offset)
Select UV Vertex.
struct BMLoop ** ED_uvedit_selected_edges(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_edges_len)
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_SELECT
Definition: WM_types.h:455
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMEdge * BM_mesh_active_edge_get(BMesh *bm)
BMVert * BM_mesh_active_vert_get(BMesh *bm)
void BM_mesh_active_face_set(BMesh *bm, BMFace *f)
BMFace * BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected)
BMFace * BM_face_at_index_find_or_table(BMesh *bm, const int index)
Definition: bmesh_mesh.cc:700
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
BMLoop * BM_loop_at_index_find(BMesh *bm, const int index)
Definition: bmesh_mesh.cc:663
LinkNode * BM_mesh_calc_path_uv_region_vert(BMesh *bm, BMElem *ele_src, BMElem *ele_dst, const uint cd_loop_uv_offset, bool(*filter_fn)(BMLoop *, void *user_data), void *user_data)
LinkNode * BM_mesh_calc_path_uv_region_face(BMesh *bm, BMElem *ele_src, BMElem *ele_dst, const uint cd_loop_uv_offset, bool(*filter_fn)(BMFace *, void *user_data), void *user_data)
LinkNode * BM_mesh_calc_path_uv_region_edge(BMesh *bm, BMElem *ele_src, BMElem *ele_dst, const uint cd_loop_uv_offset, bool(*filter_fn)(BMLoop *, void *user_data), void *user_data)
struct LinkNode * BM_mesh_calc_path_uv_vert(BMesh *bm, BMLoop *l_src, BMLoop *l_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMLoop *, void *), void *user_data)
struct LinkNode * BM_mesh_calc_path_uv_face(BMesh *bm, BMFace *f_src, BMFace *f_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMFace *, void *), void *user_data)
struct LinkNode * BM_mesh_calc_path_uv_edge(BMesh *bm, BMLoop *l_src, BMLoop *l_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMLoop *, void *), void *user_data)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
OperationNode * node
Scene scene
const Depsgraph * depsgraph
void * user_data
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
struct BMesh * bm
Definition: BKE_editmesh.h:40
BMHeader head
Definition: bmesh_class.h:243
char htype
Definition: bmesh_class.h:64
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
int totloop
Definition: bmesh_class.h:297
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
void * data
struct CheckerIntervalParams interval_params
Definition: editmesh_path.c:68
bool use_topology_distance
Definition: editmesh_path.c:64
struct ToolSettings * toolsettings
Scene * scene
Definition: uvedit_path.c:72
BMEditMesh * em
Definition: uvedit_path.c:73
uint cd_loop_uv_offset
Definition: uvedit_path.c:74
struct BMLoop * l
Definition: uvedit_intern.h:27
struct BMFace * efa
Definition: uvedit_intern.h:26
int mval[2]
Definition: WM_types.h:684
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct ReportList * reports
struct PointerRNA * ptr
BMLoop * uv_find_nearest_loop_from_vert(struct Scene *scene, struct Object *obedit, struct BMVert *v, const float co[2])
BMLoop * uv_find_nearest_loop_from_edge(struct Scene *scene, struct Object *obedit, struct BMEdge *e, const float co[2])
bool uv_find_nearest_vert(struct Scene *scene, struct Object *obedit, const float co[2], float penalty_dist, struct UvNearestHit *hit)
#define UV_NEAREST_HIT_INIT_MAX(v2d)
Definition: uvedit_intern.h:49
bool uv_find_nearest_face(struct Scene *scene, struct Object *obedit, const float co[2], struct UvNearestHit *hit)
bool uv_find_nearest_edge(struct Scene *scene, struct Object *obedit, const float co[2], float penalty, struct UvNearestHit *hit)
static bool facetag_filter_cb(BMFace *f, void *user_data_v)
Definition: uvedit_path.c:368
void UV_OT_shortest_path_pick(wmOperatorType *ot)
Definition: uvedit_path.c:753
static int mouse_mesh_uv_shortest_path_edge(Scene *scene, Object *obedit, const struct PathSelectParams *op_params, BMLoop *l_src, BMLoop *l_dst, const float aspect_y, const int cd_loop_uv_offset)
Definition: uvedit_path.c:279
static bool facetag_test_cb(BMFace *f, void *user_data_v)
Definition: uvedit_path.c:373
static bool edgetag_test_cb(BMLoop *l, void *user_data_v)
Definition: uvedit_path.c:251
static bool verttag_test_cb(BMLoop *l, void *user_data_v)
Definition: uvedit_path.c:119
static bool edgetag_filter_cb(BMLoop *l, void *user_data_v)
Definition: uvedit_path.c:246
static bool uv_shortest_path_pick_ex(Scene *scene, Depsgraph *depsgraph, Object *obedit, const struct PathSelectParams *op_params, BMElem *ele_src, BMElem *ele_dst, const float aspect_y, const int cd_loop_uv_offset)
Definition: uvedit_path.c:488
static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v)
Definition: uvedit_path.c:140
static void path_select_properties(wmOperatorType *ot)
Definition: uvedit_path.c:77
static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: uvedit_path.c:563
void UV_OT_shortest_path_select(wmOperatorType *ot)
Definition: uvedit_path.c:852
static int mouse_mesh_uv_shortest_path_vert(Scene *scene, Object *obedit, const struct PathSelectParams *op_params, BMLoop *l_src, BMLoop *l_dst, const float aspect_y, const int cd_loop_uv_offset)
Definition: uvedit_path.c:159
static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params)
Definition: uvedit_path.c:98
static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
Definition: uvedit_path.c:784
static int mouse_mesh_uv_shortest_path_face(Scene *scene, Object *obedit, const struct PathSelectParams *op_params, BMFace *f_src, BMFace *f_dst, const float aspect_y, const int cd_loop_uv_offset)
Definition: uvedit_path.c:397
static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
Definition: uvedit_path.c:388
static void edgetag_set_cb(BMLoop *l, bool val, void *user_data_v)
Definition: uvedit_path.c:270
static bool verttag_filter_cb(BMLoop *l, void *user_data_v)
Definition: uvedit_path.c:114
static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
Definition: uvedit_path.c:692
void WM_main_add_notifier(unsigned int type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalParams *op_params, int depth)
void WM_operator_properties_checker_interval_from_op(struct wmOperator *op, struct CheckerIntervalParams *op_params)
void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_disable)