LEFT | RIGHT |
1 /* | 1 /* |
2 * $Id$ | |
3 * | |
4 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
5 * | 3 * |
6 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
8 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
9 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
10 * | 8 * |
11 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
15 * | 13 * |
16 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
17 * along with this program; if not, write to the Free Software Foundation, | 15 * along with this program; if not, write to the Free Software Foundation, |
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
19 * | 17 * |
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. |
21 * All rights reserved. | 19 * All rights reserved. |
22 * | 20 * |
23 * The Original Code is: all of this file. | 21 * The Original Code is: all of this file. |
24 * | 22 * |
25 * Contributor(s): none yet. | 23 * Contributor(s): Antony Riakiotakis. |
26 * | 24 * |
27 * ***** END GPL LICENSE BLOCK ***** | 25 * ***** END GPL LICENSE BLOCK ***** |
28 */ | 26 */ |
29 | 27 |
30 /** \file blender/editors/uvedit/uvedit_ops.c | 28 /** \file blender/editors/uvedit/uvedit_ops.c |
31 * \ingroup eduv | 29 * \ingroup eduv |
32 */ | 30 */ |
33 | 31 |
34 | 32 |
35 #include <stdlib.h> | 33 #include <stdlib.h> |
36 #include <string.h> | 34 #include <string.h> |
37 #include <math.h> | 35 #include <math.h> |
| 36 #include <string.h> |
38 | 37 |
39 #include "MEM_guardedalloc.h" | 38 #include "MEM_guardedalloc.h" |
40 | 39 |
41 #include "DNA_object_types.h" | 40 #include "DNA_object_types.h" |
| 41 #include "DNA_material_types.h" |
| 42 #include "DNA_mesh_types.h" |
42 #include "DNA_meshdata_types.h" | 43 #include "DNA_meshdata_types.h" |
| 44 #include "DNA_node_types.h" |
| 45 #include "DNA_image_types.h" |
| 46 #include "DNA_space_types.h" |
43 #include "DNA_scene_types.h" | 47 #include "DNA_scene_types.h" |
44 | 48 |
| 49 #include "BLI_utildefines.h" |
| 50 #include "BLI_alloca.h" |
45 #include "BLI_math.h" | 51 #include "BLI_math.h" |
| 52 #include "BLI_lasso.h" |
46 #include "BLI_blenlib.h" | 53 #include "BLI_blenlib.h" |
47 #include "BLI_editVert.h" | 54 #include "BLI_array.h" |
48 #include "BLI_utildefines.h" | |
49 | 55 |
50 #include "BKE_context.h" | 56 #include "BKE_context.h" |
51 #include "BKE_customdata.h" | 57 #include "BKE_customdata.h" |
52 #include "BKE_depsgraph.h" | 58 #include "BKE_depsgraph.h" |
53 #include "BKE_image.h" | 59 #include "BKE_image.h" |
54 #include "BKE_library.h" | 60 #include "BKE_library.h" |
| 61 #include "BKE_main.h" |
| 62 #include "BKE_material.h" |
55 #include "BKE_mesh.h" | 63 #include "BKE_mesh.h" |
| 64 #include "BKE_node.h" |
56 #include "BKE_report.h" | 65 #include "BKE_report.h" |
| 66 #include "BKE_scene.h" |
| 67 #include "BKE_editmesh.h" |
57 | 68 |
58 #include "ED_image.h" | 69 #include "ED_image.h" |
59 #include "ED_mesh.h" | 70 #include "ED_mesh.h" |
| 71 #include "ED_node.h" |
60 #include "ED_uvedit.h" | 72 #include "ED_uvedit.h" |
61 #include "ED_object.h" | 73 #include "ED_object.h" |
62 #include "ED_screen.h" | 74 #include "ED_screen.h" |
63 #include "ED_transform.h" | 75 #include "ED_transform.h" |
64 | 76 |
65 #include "RNA_access.h" | 77 #include "RNA_access.h" |
66 #include "RNA_define.h" | 78 #include "RNA_define.h" |
67 | 79 |
68 #include "WM_api.h" | 80 #include "WM_api.h" |
69 #include "WM_types.h" | 81 #include "WM_types.h" |
70 | 82 |
71 #include "UI_view2d.h" | 83 #include "UI_view2d.h" |
72 | 84 |
73 #include "uvedit_intern.h" | 85 #include "uvedit_intern.h" |
74 | 86 |
| 87 static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
action); |
| 88 static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
*obedit, const bool select); |
| 89 static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
*obedit, const bool select); |
| 90 |
75 /************************* state testing ************************/ | 91 /************************* state testing ************************/ |
76 | 92 |
77 int ED_uvedit_test(Object *obedit) | 93 int ED_uvedit_test(Object *obedit) |
78 { | 94 { |
79 » EditMesh *em; | 95 » BMEditMesh *em; |
80 int ret; | 96 int ret; |
81 | 97 |
82 » if(!obedit || obedit->type != OB_MESH) | 98 » if (!obedit) |
| 99 » » return 0; |
| 100 »······· |
| 101 » if (obedit->type != OB_MESH) |
83 return 0; | 102 return 0; |
84 | 103 |
85 » em = BKE_mesh_get_editmesh(obedit->data); | 104 » em = BKE_editmesh_from_object(obedit); |
86 » ret = EM_texFaceCheck(em); | 105 » ret = EDBM_mtexpoly_check(em); |
87 » BKE_mesh_end_editmesh(obedit->data, em); | |
88 ········ | 106 ········ |
89 return ret; | 107 return ret; |
90 } | 108 } |
91 | 109 |
92 /************************* assign image ************************/ | 110 static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C) |
| 111 { |
| 112 » SpaceImage *sima = CTX_wm_space_image(C); |
| 113 » ToolSettings *toolsettings = CTX_data_tool_settings(C); |
| 114 » Object *obedit = CTX_data_edit_object(C); |
93 | 115 |
94 void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre
vima) | 116 » return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_u
v_sculpt); |
| 117 } |
| 118 |
| 119 static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C) |
95 { | 120 { |
96 » EditMesh *em; | 121 » Object *ob = CTX_data_active_object(C); |
97 » EditFace *efa; | |
98 » MTFace *tf; | |
99 » int update= 0; | |
100 »······· | |
101 » /* skip assigning these procedural images... */ | |
102 » if(ima && (ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE
)) | |
103 » » return; | |
104 | 122 |
105 » /* verify we have a mesh we can work with */ | 123 » if (ob && ob->type == OB_MESH) { |
106 » if(!obedit || (obedit->type != OB_MESH)) | 124 » » Mesh *me = ob->data; |
107 » » return; | |
108 | |
109 » em= BKE_mesh_get_editmesh(((Mesh*)obedit->data)); | |
110 » if(!em || !em->faces.first) { | |
111 » » BKE_mesh_end_editmesh(obedit->data, em); | |
112 » » return; | |
113 » } | |
114 »······· | |
115 » /* ensure we have a uv layer */ | |
116 » if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) { | |
117 » » EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL); | |
118 » » update= 1; | |
119 » } | |
120 | |
121 » /* now assign to all visible faces */ | |
122 » for(efa= em->faces.first; efa; efa= efa->next) { | |
123 » » tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
124 | |
125 if(uvedit_face_visible(scene, previma, efa, tf)) { | 125 if(uvedit_face_visible(scene, previma, efa, tf)) { |
126 if(ima) { | 126 if(ima) { |
127 tf->tpage= ima; | 127 tf->tpage= ima; |
| 128 tf->mode |= TF_TEX; |
128 ································ | 129 ································ |
129 if(ima->id.us==0) id_us_plus(&ima->id); | 130 if(ima->id.us==0) id_us_plus(&ima->id); |
130 else id_lib_extern(&ima->id); | 131 else id_lib_extern(&ima->id); |
131 } | 132 } |
132 else { | 133 else { |
133 tf->tpage= NULL; | 134 tf->tpage= NULL; |
| 135 tf->mode &= ~TF_TEX; |
134 } | 136 } |
135 | 137 |
136 update = 1; | 138 update = 1; |
137 } | |
138 } | |
139 | |
140 /* and update depdency graph */ | |
141 if(update) | |
142 DAG_id_tag_update(obedit->data, 0); | |
143 | |
144 BKE_mesh_end_editmesh(obedit->data, em); | |
145 } | |
146 | |
147 /* dotile - 1, set the tile flag (from the space image) | |
148 * 2, set the tile index for the faces. */ | |
149 static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) | |
150 { | |
151 EditMesh *em; | |
152 EditFace *efa; | |
153 MTFace *tf; | |
154 ········ | |
155 /* verify if we have something to do */ | |
156 if(!ima || !ED_uvedit_test(obedit)) | |
157 return 0; | |
158 | |
159 if((ima->tpageflag & IMA_TILES) == 0) | |
160 return 0; | |
161 | |
162 /* skip assigning these procedural images... */ | |
163 if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE) | |
164 return 0; | |
165 ········ | |
166 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
167 | |
168 for(efa= em->faces.first; efa; efa= efa->next) { | |
169 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
170 | |
171 if(efa->h==0 && efa->f & SELECT) | |
172 tf->tile= curtile; /* set tile index */ | |
173 } | |
174 | |
175 DAG_id_tag_update(obedit->data, 0); | |
176 BKE_mesh_end_editmesh(obedit->data, em); | |
177 | |
178 return 1; | |
179 } | |
180 | |
181 /*********************** space conversion *********************/ | |
182 | |
183 static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
) | |
184 { | |
185 int width, height; | |
186 | |
187 if(sima) { | |
188 ED_space_image_size(sima, &width, &height); | |
189 } | |
190 else { | |
191 width= 256; | |
192 height= 256; | |
193 } | |
194 | |
195 dist[0]= pixeldist/width; | |
196 dist[1]= pixeldist/height; | |
197 } | |
198 | |
199 /*************** visibility and selection utilities **************/ | |
200 | |
201 int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa) | |
202 { | |
203 ToolSettings *ts= scene->toolsettings; | |
204 | |
205 if(ts->uv_flag & UV_SYNC_SELECTION) | |
206 return (efa->h==0); | |
207 else | |
208 return (efa->h==0 && (efa->f & SELECT)); | |
209 } | |
210 | |
211 int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf) | |
212 { | |
213 ToolSettings *ts= scene->toolsettings; | |
214 | |
215 if(ts->uv_flag & UV_SHOW_SAME_IMAGE) | |
216 return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa)
: 0; | |
217 else | |
218 return uvedit_face_visible_nolocal(scene, efa); | |
219 } | |
220 | |
221 int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf) | |
222 { | |
223 ToolSettings *ts= scene->toolsettings; | |
224 | |
225 if(ts->uv_flag & UV_SYNC_SELECTION) | |
226 return (efa->f & SELECT); | |
227 else | |
228 return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 ||
tf->flag & TF_SEL4)); | |
229 } | |
230 | |
231 void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf) | |
232 { | |
233 ToolSettings *ts= scene->toolsettings; | |
234 | |
235 if(ts->uv_flag & UV_SYNC_SELECTION) | |
236 EM_select_face(efa, 1); | |
237 else | |
238 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); | |
239 } | |
240 | |
241 void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf) | |
242 { | |
243 ToolSettings *ts= scene->toolsettings; | |
244 | |
245 if(ts->uv_flag & UV_SYNC_SELECTION) | |
246 EM_select_face(efa, 0); | |
247 else | |
248 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); | |
249 } | |
250 | |
251 int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
252 { | |
253 ToolSettings *ts= scene->toolsettings; | |
254 int nvert= (efa->v4)? 4: 3; | |
255 | |
256 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
257 if(ts->selectmode & SCE_SELECT_FACE) | |
258 return (efa->f & SELECT); | |
259 else if(ts->selectmode & SCE_SELECT_EDGE) | |
260 return (*(&efa->e1 + i))->f & SELECT; | |
261 else | |
262 return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)
%nvert)->f & SELECT)); | |
263 } | |
264 else | |
265 return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i
+1)%nvert)); | |
266 } | |
267 | |
268 void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
269 { | |
270 ToolSettings *ts= scene->toolsettings; | |
271 int nvert= (efa->v4)? 4: 3; | |
272 | |
273 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
274 if(ts->selectmode & SCE_SELECT_FACE) | |
275 EM_select_face(efa, 1); | |
276 else if(ts->selectmode & SCE_SELECT_EDGE) | |
277 EM_select_edge((*(&efa->e1 + i)), 1); | |
278 else { | |
279 (efa->v1 + i)->f |= SELECT; | |
280 (efa->v1 + (i+1)%nvert)->f |= SELECT; | |
281 } | |
282 } | |
283 else | |
284 tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert); | |
285 } | |
286 | |
287 void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
288 { | |
289 ToolSettings *ts= scene->toolsettings; | |
290 int nvert= (efa->v4)? 4: 3; | |
291 | |
292 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
293 if(ts->selectmode & SCE_SELECT_FACE) | |
294 EM_select_face(efa, 0); | |
295 else if(ts->selectmode & SCE_SELECT_EDGE) | |
296 EM_select_edge((*(&efa->e1 + i)), 0); | |
297 else { | |
298 (efa->v1 + i)->f &= ~SELECT; | |
299 (efa->v1 + (i+1)%nvert)->f &= ~SELECT; | |
300 } | |
301 } | |
302 else | |
303 tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert)); | |
304 } | |
305 | |
306 int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
307 { | |
308 ToolSettings *ts= scene->toolsettings; | |
309 | |
310 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
311 if(ts->selectmode & SCE_SELECT_FACE) | |
312 return (efa->f & SELECT); | |
313 else | |
314 return (*(&efa->v1 + i))->f & SELECT; | |
315 } | |
316 else | |
317 return tf->flag & TF_SEL_MASK(i); | |
318 } | |
319 | |
320 void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
321 { | |
322 ToolSettings *ts= scene->toolsettings; | |
323 | |
324 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
325 if(ts->selectmode & SCE_SELECT_FACE) | |
326 EM_select_face(efa, 1); | |
327 else | |
328 (*(&efa->v1 + i))->f |= SELECT; | |
329 } | |
330 else | |
331 tf->flag |= TF_SEL_MASK(i); | |
332 } | |
333 | |
334 void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) | |
335 { | |
336 ToolSettings *ts= scene->toolsettings; | |
337 | |
338 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
339 if(ts->selectmode & SCE_SELECT_FACE) | |
340 EM_select_face(efa, 0); | |
341 else | |
342 (*(&efa->v1 + i))->f &= ~SELECT; | |
343 } | |
344 else | |
345 tf->flag &= ~TF_SEL_MASK(i); | |
346 } | |
347 | |
348 /*********************** live unwrap utilities ***********************/ | |
349 | |
350 static void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *ob
edit) | |
351 { | |
352 if(sima && (sima->flag & SI_LIVE_UNWRAP)) { | |
353 ED_uvedit_live_unwrap_begin(scene, obedit); | |
354 ED_uvedit_live_unwrap_re_solve(); | |
355 ED_uvedit_live_unwrap_end(0); | |
356 } | |
357 } | |
358 | |
359 /*********************** geometric utilities ***********************/ | |
360 | |
361 void uv_center(float uv[][2], float cent[2], int quad) | |
362 { | |
363 if(quad) { | |
364 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0f; | |
365 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0f; | |
366 } | |
367 else { | |
368 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0f; | |
369 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0f; | |
370 } | |
371 } | |
372 | |
373 float uv_area(float uv[][2], int quad) | |
374 { | |
375 if(quad) | |
376 return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[
2], uv[3]);· | |
377 else | |
378 return area_tri_v2(uv[0], uv[1], uv[2]);· | |
379 } | |
380 | |
381 void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy) | |
382 { | |
383 uv[0][0] = uv_orig[0][0]*aspx; | |
384 uv[0][1] = uv_orig[0][1]*aspy; | |
385 ········ | |
386 uv[1][0] = uv_orig[1][0]*aspx; | |
387 uv[1][1] = uv_orig[1][1]*aspy; | |
388 ········ | |
389 uv[2][0] = uv_orig[2][0]*aspx; | |
390 uv[2][1] = uv_orig[2][1]*aspy; | |
391 ········ | |
392 uv[3][0] = uv_orig[3][0]*aspx; | |
393 uv[3][1] = uv_orig[3][1]*aspy; | |
394 } | |
395 | |
396 int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float
*max) | |
397 { | |
398 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
399 EditFace *efa; | |
400 MTFace *tf; | |
401 int sel; | |
402 | |
403 INIT_MINMAX2(min, max); | |
404 | |
405 sel= 0; | |
406 for(efa= em->faces.first; efa; efa= efa->next) { | |
407 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
408 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
409 if(uvedit_uv_selected(scene, efa, tf, 0))
{ DO_MINMAX2(tf->uv[0], min, max); sel = 1; } | |
410 if(uvedit_uv_selected(scene, efa, tf, 1))
{ DO_MINMAX2(tf->uv[1], min, max); sel = 1; } | |
411 if(uvedit_uv_selected(scene, efa, tf, 2))
{ DO_MINMAX2(tf->uv[2], min, max); sel = 1; } | |
412 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))
{ DO_MINMAX2(tf->uv[3], min, max); sel = 1; } | |
413 } | |
414 } | |
415 ········ | |
416 BKE_mesh_end_editmesh(obedit->data, em); | |
417 return sel; | |
418 } | |
419 | |
420 static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[3
]) | |
421 { | |
422 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
423 EditFace *efa; | |
424 MTFace *tf; | |
425 unsigned int sel= 0; | |
426 | |
427 zero_v3(co); | |
428 | |
429 for(efa= em->faces.first; efa; efa= efa->next) { | |
430 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
431 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
432 if(uvedit_uv_selected(scene, efa, tf, 0))
{ add_v3_v3(co, tf->uv[0]); sel++; } | |
433 if(uvedit_uv_selected(scene, efa, tf, 1))
{ add_v3_v3(co, tf->uv[1]); sel++; } | |
434 if(uvedit_uv_selected(scene, efa, tf, 2))
{ add_v3_v3(co, tf->uv[2]); sel++; } | |
435 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))
{ add_v3_v3(co, tf->uv[3]); sel++; } | |
436 } | |
437 } | |
438 | |
439 mul_v3_fl(co, 1.0f/(float)sel); | |
440 | |
441 BKE_mesh_end_editmesh(obedit->data, em); | |
442 return (sel != 0); | |
443 } | |
444 | |
445 static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent,
char mode) | |
446 { | |
447 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
448 float min[2], max[2]; | |
449 int change= 0; | |
450 ········ | |
451 if(mode==V3D_CENTER) { /* bounding box */ | |
452 if(ED_uvedit_minmax(scene, ima, obedit, min, max)) { | |
453 change = 1; | |
454 | |
455 cent[0]= (min[0]+max[0])/2.0f; | |
456 cent[1]= (min[1]+max[1])/2.0f; | |
457 } | |
458 } | |
459 else { | |
460 if(ED_uvedit_median(scene, ima, obedit, cent)) { | |
461 change = 1; | |
462 } | |
463 | |
464 } | |
465 | |
466 if(change) { | |
467 BKE_mesh_end_editmesh(obedit->data, em); | |
468 return 1; | |
469 } | |
470 | |
471 BKE_mesh_end_editmesh(obedit->data, em); | |
472 return 0; | |
473 } | |
474 | |
475 /************************** find nearest ****************************/ | |
476 | |
477 typedef struct NearestHit { | |
478 EditFace *efa; | |
479 MTFace *tf; | |
480 | |
481 int vert, uv; | |
482 int edge, vert2; | |
483 } NearestHit; | |
484 | |
485 static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float c
o[2], NearestHit *hit) | |
486 { | |
487 MTFace *tf; | |
488 EditFace *efa; | |
489 EditVert *eve; | |
490 float mindist, dist; | |
491 int i, nverts; | |
492 | |
493 mindist= 1e10f; | |
494 memset(hit, 0, sizeof(*hit)); | |
495 | |
496 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) | |
497 eve->tmp.l = i; | |
498 ········ | |
499 for(efa= em->faces.first; efa; efa= efa->next) { | |
500 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
501 | |
502 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
503 nverts= efa->v4? 4: 3; | |
504 | |
505 for(i=0; i<nverts; i++) { | |
506 dist= dist_to_line_segment_v2(co, tf->uv[i], tf-
>uv[(i+1)%nverts]); | |
507 | |
508 if(dist < mindist) { | |
509 hit->tf= tf; | |
510 hit->efa= efa; | |
511 hit->edge= i; | |
512 mindist= dist; | |
513 | |
514 hit->vert= (*(&efa->v1 + i))->tmp.l; | |
515 hit->vert2= (*(&efa->v1 + ((i+1)%nverts)
))->tmp.l; | |
516 } | |
517 } | |
518 } | |
519 } | |
520 } | |
521 | |
522 static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float c
o[2], NearestHit *hit) | |
523 { | |
524 MTFace *tf; | |
525 EditFace *efa; | |
526 float mindist, dist, cent[2]; | |
527 int i, nverts; | |
528 | |
529 mindist= 1e10f; | |
530 memset(hit, 0, sizeof(*hit)); | |
531 ········ | |
532 for(efa= em->faces.first; efa; efa= efa->next) { | |
533 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
534 | |
535 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
536 nverts= efa->v4? 4: 3; | |
537 cent[0]= cent[1]= 0.0f; | |
538 | |
539 for(i=0; i<nverts; i++) { | |
540 cent[0] += tf->uv[i][0]; | |
541 cent[1] += tf->uv[i][1]; | |
542 } | |
543 | |
544 cent[0] /= nverts; | |
545 cent[1] /= nverts; | |
546 dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]); | |
547 | |
548 if(dist < mindist) { | |
549 hit->tf= tf; | |
550 hit->efa= efa; | |
551 mindist= dist; | |
552 } | |
553 } | |
554 } | |
555 } | |
556 | |
557 static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float
uv[2]) | |
558 { | |
559 float m[3], v1[3], v2[3], c1, c2; | |
560 int id1, id2; | |
561 | |
562 id1= (id+nverts-1)%nverts; | |
563 id2= (id+nverts+1)%nverts; | |
564 | |
565 m[0]= co[0]-uv[0]; | |
566 m[1]= co[1]-uv[1]; | |
567 sub_v2_v2v2(v1, tf->uv[id1], tf->uv[id]); | |
568 sub_v2_v2v2(v2, tf->uv[id2], tf->uv[id]); | |
569 | |
570 /* m and v2 on same side of v-v1? */ | |
571 c1= v1[0]*m[1] - v1[1]*m[0]; | |
572 c2= v1[0]*v2[1] - v1[1]*v2[0]; | |
573 | |
574 if(c1*c2 < 0.0f) | |
575 return 0; | |
576 | |
577 /* m and v1 on same side of v-v2? */ | |
578 c1= v2[0]*m[1] - v2[1]*m[0]; | |
579 c2= v2[0]*v1[1] - v2[1]*v1[0]; | |
580 | |
581 return (c1*c2 >= 0.0f); | |
582 } | |
583 | |
584 static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float c
o[2], float penalty[2], NearestHit *hit) | |
585 { | |
586 EditFace *efa; | |
587 EditVert *eve; | |
588 MTFace *tf; | |
589 float mindist, dist; | |
590 int i, nverts; | |
591 | |
592 mindist= 1e10f; | |
593 memset(hit, 0, sizeof(*hit)); | |
594 ········ | |
595 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) | |
596 eve->tmp.l = i; | |
597 ········ | |
598 for(efa= em->faces.first; efa; efa= efa->next) { | |
599 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
600 | |
601 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
602 nverts= efa->v4? 4: 3; | |
603 | |
604 for(i=0; i<nverts; i++) { | |
605 if(penalty && uvedit_uv_selected(scene, efa, tf,
i)) | |
606 dist= fabsf(co[0]-tf->uv[i][0])+penalty[
0] + fabsf(co[1]-tf->uv[i][1]) + penalty[1]; | |
607 else | |
608 dist= fabsf(co[0]-tf->uv[i][0]) + fabsf(
co[1]-tf->uv[i][1]); | |
609 | |
610 if(dist<=mindist) { | |
611 if(dist==mindist) | |
612 if(!nearest_uv_between(tf, nvert
s, i, co, tf->uv[i])) | |
613 continue; | |
614 | |
615 mindist= dist; | |
616 | |
617 hit->uv= i; | |
618 hit->tf= tf; | |
619 hit->efa= efa; | |
620 | |
621 hit->vert= (*(&efa->v1 + i))->tmp.l; | |
622 } | |
623 } | |
624 } | |
625 } | |
626 } | |
627 | |
628 int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2],
float uv[2]) | |
629 { | |
630 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
631 EditFace *efa; | |
632 MTFace *tf; | |
633 float mindist, dist; | |
634 int i, nverts, found= 0; | |
635 | |
636 mindist= 1e10f; | |
637 uv[0]= co[0]; | |
638 uv[1]= co[1]; | |
639 ········ | |
640 for(efa= em->faces.first; efa; efa= efa->next) { | |
641 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
642 | |
643 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
644 nverts= efa->v4? 4: 3; | |
645 | |
646 for(i=0; i<nverts; i++) { | |
647 if(uvedit_uv_selected(scene, efa, tf, i)) | |
648 continue; | |
649 | |
650 dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->
uv[i][1]); | |
651 | |
652 if(dist<=mindist) { | |
653 mindist= dist; | |
654 | |
655 uv[0]= tf->uv[i][0]; | |
656 uv[1]= tf->uv[i][1]; | |
657 found= 1; | |
658 } | |
659 } | |
660 } | |
661 } | |
662 | |
663 BKE_mesh_end_editmesh(obedit->data, em); | |
664 return found; | |
665 } | |
666 | |
667 /*********************** loop select ***********************/ | |
668 | |
669 static void uv_vertex_loop_flag(UvMapVert *first) | |
670 { | |
671 UvMapVert *iterv; | |
672 int count= 0; | |
673 | |
674 for(iterv=first; iterv; iterv=iterv->next) { | |
675 if(iterv->separate && iterv!=first) | |
676 break; | |
677 | |
678 count++; | |
679 } | |
680 ········ | |
681 if(count < 5) | |
682 first->flag= 1; | |
683 } | |
684 | |
685 static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a) | |
686 { | |
687 UvMapVert *iterv, *first; | |
688 ········ | |
689 first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l); | |
690 | |
691 for(iterv=first; iterv; iterv=iterv->next) { | |
692 if(iterv->separate) | |
693 first= iterv; | |
694 if(iterv->f == efa->tmp.l) | |
695 return first; | |
696 } | |
697 ········ | |
698 return NULL; | |
699 } | |
700 | |
701 static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) | |
702 { | |
703 UvMapVert *iterv1, *iterv2; | |
704 EditFace *efa; | |
705 int tot = 0; | |
706 | |
707 /* count number of faces this edge has */ | |
708 for(iterv1=first1; iterv1; iterv1=iterv1->next) { | |
709 if(iterv1->separate && iterv1 != first1) | |
710 break; | |
711 | |
712 for(iterv2=first2; iterv2; iterv2=iterv2->next) { | |
713 if(iterv2->separate && iterv2 != first2) | |
714 break; | |
715 | |
716 if(iterv1->f == iterv2->f) { | |
717 /* if face already tagged, don't do this edge */ | |
718 efa= EM_get_face_for_index(iterv1->f); | |
719 if(efa->f1) | |
720 return 0; | |
721 | |
722 tot++; | |
723 break; | |
724 } | |
725 } | |
726 } | |
727 | |
728 if(*totface == 0) /* start edge */ | |
729 *totface= tot; | |
730 else if(tot != *totface) /* check for same number of faces as start edge
*/ | |
731 return 0; | |
732 | |
733 /* tag the faces */ | |
734 for(iterv1=first1; iterv1; iterv1=iterv1->next) { | |
735 if(iterv1->separate && iterv1 != first1) | |
736 break; | |
737 | |
738 for(iterv2=first2; iterv2; iterv2=iterv2->next) { | |
739 if(iterv2->separate && iterv2 != first2) | |
740 break; | |
741 | |
742 if(iterv1->f == iterv2->f) { | |
743 efa= EM_get_face_for_index(iterv1->f); | |
744 efa->f1= 1; | |
745 break; | |
746 } | |
747 } | |
748 } | |
749 | |
750 return 1; | |
751 } | |
752 | |
753 static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
it, float limit[2], int extend) | |
754 { | |
755 EditVert *eve; | |
756 EditFace *efa; | |
757 MTFace *tf; | |
758 UvVertMap *vmap; | |
759 UvMapVert *iterv1, *iterv2; | |
760 int a, count, looking, nverts, starttotf, select; | |
761 | |
762 /* setup */ | |
763 EM_init_index_arrays(em, 0, 0, 1); | |
764 vmap= EM_make_uv_vert_map(em, 0, 0, limit); | |
765 | |
766 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) | |
767 eve->tmp.l = count; | |
768 | |
769 for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) { | |
770 if(!extend) { | |
771 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
772 uvedit_face_deselect(scene, efa, tf); | |
773 } | |
774 | |
775 efa->tmp.l= count; | |
776 efa->f1= 0; | |
777 } | |
778 ········ | |
779 /* set flags for first face and verts */ | |
780 nverts= (hit->efa->v4)? 4: 3; | |
781 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); | |
782 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); | |
783 uv_vertex_loop_flag(iterv1); | |
784 uv_vertex_loop_flag(iterv2); | |
785 | |
786 starttotf= 0; | |
787 uv_edge_tag_faces(iterv1, iterv2, &starttotf); | |
788 | |
789 /* sorry, first edge isnt even ok */ | |
790 if(iterv1->flag==0 && iterv2->flag==0) looking= 0; | |
791 else looking= 1; | |
792 | |
793 /* iterate */ | |
794 while(looking) { | |
795 looking= 0; | |
796 | |
797 /* find correct valence edges which are not tagged yet, but conn
ect to tagged one */ | |
798 for(efa= em->faces.first; efa; efa=efa->next) { | |
799 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
800 | |
801 if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf))
{ | |
802 nverts= (efa->v4)? 4: 3; | |
803 for(a=0; a<nverts; a++) { | |
804 /* check face not hidden and not tagged
*/ | |
805 iterv1= uv_vertex_map_get(vmap, efa, a); | |
806 iterv2= uv_vertex_map_get(vmap, efa, (a+
1)%nverts); | |
807 | |
808 /* check if vertex is tagged and has rig
ht valence */ | |
809 if(iterv1->flag || iterv2->flag) { | |
810 if(uv_edge_tag_faces(iterv1, ite
rv2, &starttotf)) { | |
811 looking= 1; | |
812 efa->f1= 1; | |
813 | |
814 uv_vertex_loop_flag(iter
v1); | |
815 uv_vertex_loop_flag(iter
v2); | |
816 break; | |
817 } | |
818 } | |
819 } | |
820 } | |
821 } | |
822 } | |
823 | |
824 /* do the actual select/deselect */ | |
825 nverts= (hit->efa->v4)? 4: 3; | |
826 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); | |
827 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); | |
828 iterv1->flag= 1; | |
829 iterv2->flag= 1; | |
830 | |
831 if(extend) { | |
832 tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE); | |
833 | |
834 if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge)) | |
835 select= 0; | |
836 else | |
837 select= 1; | |
838 } | |
839 else | |
840 select= 1; | |
841 ········ | |
842 for(efa= em->faces.first; efa; efa=efa->next) { | |
843 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
844 | |
845 nverts= (efa->v4)? 4: 3; | |
846 for(a=0; a<nverts; a++) { | |
847 iterv1= uv_vertex_map_get(vmap, efa, a); | |
848 | |
849 if(iterv1->flag) { | |
850 if(select) uvedit_uv_select(scene, efa, tf, a); | |
851 else uvedit_uv_deselect(scene, efa, tf, a); | |
852 } | |
853 } | |
854 } | |
855 | |
856 /* cleanup */ | |
857 EM_free_uv_vert_map(vmap); | |
858 EM_free_index_arrays(); | |
859 | |
860 return (select)? 1: -1; | |
861 } | |
862 | |
863 /*********************** linked select ***********************/ | |
864 | |
865 static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2]
, NearestHit *hit, int extend) | |
866 { | |
867 EditFace *efa; | |
868 MTFace *tf; | |
869 UvVertMap *vmap; | |
870 UvMapVert *vlist, *iterv, *startv; | |
871 int i, nverts, stacksize= 0, *stack; | |
872 unsigned int a; | |
873 char *flag; | |
874 | |
875 EM_init_index_arrays(em, 0, 0, 1); /* we can use this too */ | |
876 vmap= EM_make_uv_vert_map(em, 1, 0, limit); | |
877 if(vmap == NULL) | |
878 return; | |
879 | |
880 stack= MEM_mallocN(sizeof(*stack) * em->totface, "UvLinkStack"); | |
881 flag= MEM_callocN(sizeof(*flag) * em->totface, "UvLinkFlag"); | |
882 | |
883 if(!hit) { | |
884 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { | |
885 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
886 | |
887 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
888 const char select_flag= efa->v4 ? (TF_SEL1|TF_SE
L2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
889 if(tf->flag & select_flag) { | |
890 stack[stacksize]= a; | |
891 stacksize++; | |
892 flag[a]= 1; | |
893 } | |
894 } | |
895 } | |
896 } | |
897 else { | |
898 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { | |
899 if(efa == hit->efa) { | |
900 stack[stacksize]= a; | |
901 stacksize++; | |
902 flag[a]= 1; | |
903 break; | |
904 } | |
905 } | |
906 } | |
907 | |
908 while(stacksize > 0) { | |
909 stacksize--; | |
910 a= stack[stacksize]; | |
911 | |
912 efa = EM_get_face_for_index(a); | |
913 | |
914 nverts= efa->v4? 4: 3; | |
915 | |
916 for(i=0; i<nverts; i++) { | |
917 /* make_uv_vert_map_EM sets verts tmp.l to the indices *
/ | |
918 vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l
); | |
919 ························ | |
920 startv= vlist; | |
921 | |
922 for(iterv=vlist; iterv; iterv=iterv->next) { | |
923 if(iterv->separate) | |
924 startv= iterv; | |
925 if(iterv->f == a) | |
926 break; | |
927 } | |
928 | |
929 for(iterv=startv; iterv; iterv=iterv->next) { | |
930 if((startv != iterv) && (iterv->separate)) | |
931 break; | |
932 else if(!flag[iterv->f]) { | |
933 flag[iterv->f]= 1; | |
934 stack[stacksize]= iterv->f; | |
935 stacksize++; | |
936 } | |
937 } | |
938 } | |
939 } | |
940 | |
941 if(!extend) { | |
942 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { | |
943 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
944 if(flag[a]) | |
945 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); | |
946 else | |
947 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); | |
948 } | |
949 } | |
950 else { | |
951 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { | |
952 if(flag[a]) { | |
953 const char select_flag= efa->v4 ? (TF_SEL1|TF_SE
L2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
954 tf = CustomData_em_get(&em->fdata, efa->data, CD
_MTFACE); | |
955 if((tf->flag & select_flag)) | |
956 break; | |
957 } | |
958 } | |
959 | |
960 if(efa) { | |
961 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++)
{ | |
962 if(flag[a]) { | |
963 tf = CustomData_em_get(&em->fdata, efa->
data, CD_MTFACE); | |
964 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
965 } | |
966 } | |
967 } | |
968 else { | |
969 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++)
{ | |
970 if(flag[a]) { | |
971 tf = CustomData_em_get(&em->fdata, efa->
data, CD_MTFACE); | |
972 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_
SEL4); | |
973 } | |
974 } | |
975 } | |
976 } | |
977 ········ | |
978 MEM_freeN(stack); | |
979 MEM_freeN(flag); | |
980 EM_free_uv_vert_map(vmap); | |
981 EM_free_index_arrays(); | |
982 } | |
983 | |
984 /* ******************** align operator **************** */ | |
985 | |
986 static void weld_align_uv(bContext *C, int tool) | |
987 { | |
988 SpaceImage *sima; | |
989 Scene *scene; | |
990 Object *obedit; | |
991 Image *ima; | |
992 EditMesh *em; | |
993 EditFace *efa; | |
994 MTFace *tf; | |
995 float cent[2], min[2], max[2]; | |
996 ········ | |
997 scene= CTX_data_scene(C); | |
998 obedit= CTX_data_edit_object(C); | |
999 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
1000 ima= CTX_data_edit_image(C); | |
1001 sima= CTX_wm_space_image(C); | |
1002 | |
1003 INIT_MINMAX2(min, max); | |
1004 | |
1005 if(tool == 'a') { | |
1006 for(efa= em->faces.first; efa; efa= efa->next) { | |
1007 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1008 | |
1009 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1010 if(uvedit_uv_selected(scene, efa, tf, 0)) | |
1011 DO_MINMAX2(tf->uv[0], min, max) | |
1012 if(uvedit_uv_selected(scene, efa, tf, 1)) | |
1013 DO_MINMAX2(tf->uv[1], min, max) | |
1014 if(uvedit_uv_selected(scene, efa, tf, 2)) | |
1015 DO_MINMAX2(tf->uv[2], min, max) | |
1016 if(efa->v4 && uvedit_uv_selected(scene, efa, tf,
3)) | |
1017 DO_MINMAX2(tf->uv[3], min, max) | |
1018 } | |
1019 } | |
1020 | |
1021 tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x'; | |
1022 } | |
1023 | |
1024 uvedit_center(scene, ima, obedit, cent, 0); | |
1025 | |
1026 if(tool == 'x' || tool == 'w') { | |
1027 for(efa= em->faces.first; efa; efa= efa->next) { | |
1028 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1029 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1030 if(uvedit_uv_selected(scene, efa, tf, 0)) | |
1031 tf->uv[0][0]= cent[0]; | |
1032 if(uvedit_uv_selected(scene, efa, tf, 1)) | |
1033 tf->uv[1][0]= cent[0]; | |
1034 if(uvedit_uv_selected(scene, efa, tf, 2)) | |
1035 tf->uv[2][0]= cent[0]; | |
1036 if(efa->v4 && uvedit_uv_selected(scene, efa, tf,
3)) | |
1037 tf->uv[3][0]= cent[0]; | |
1038 } | |
1039 } | |
1040 } | |
1041 | |
1042 if(tool == 'y' || tool == 'w') { | |
1043 for(efa= em->faces.first; efa; efa= efa->next) { | |
1044 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1045 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1046 if(uvedit_uv_selected(scene, efa, tf, 0)) | |
1047 tf->uv[0][1]= cent[1]; | |
1048 if(uvedit_uv_selected(scene, efa, tf, 1)) | |
1049 tf->uv[1][1]= cent[1]; | |
1050 if(uvedit_uv_selected(scene, efa, tf, 2)) | |
1051 tf->uv[2][1]= cent[1]; | |
1052 if(efa->v4 && uvedit_uv_selected(scene, efa, tf,
3)) | |
1053 tf->uv[3][1]= cent[1]; | |
1054 } | |
1055 } | |
1056 } | |
1057 | |
1058 if(tool == 's' || tool == 't' || tool == 'u') { | |
1059 /* pass 1&2 variables */ | |
1060 int i, j; | |
1061 int starttmpl= -1, connectedtostarttmpl= -1, startcorner; | |
1062 int endtmpl= -1, connectedtoendtmpl= -1, endcorner; | |
1063 MTFace *startface, *endface; | |
1064 int itmpl, jtmpl; | |
1065 EditVert *eve; | |
1066 int pass; /* first 2 passes find endpoints, 3rd pass moves middl
e points, 4th pass is fail-on-face-selected */ | |
1067 EditFace *startefa, *endefa; | |
1068 | |
1069 /* pass 3 variables */ | |
1070 float startx, starty, firstm, firstb, midx, midy; | |
1071 float endx, endy, secondm, secondb, midmovedx, midmovedy; | |
1072 float IsVertical_check= -1; | |
1073 float IsHorizontal_check= -1; | |
1074 | |
1075 for(i= 0, eve= em->verts.first; eve; eve= eve->next, i++) /* giv
e each point a unique name */ | |
1076 eve->tmp.l= i; | |
1077 for(pass= 1; pass <= 3; pass++) { /* do this for each endpoint *
/ | |
1078 if(pass == 3){ /* calculate */ | |
1079 startx= startface->uv[startcorner][0]; | |
1080 starty= startface->uv[startcorner][1]; | |
1081 endx= endface->uv[endcorner][0]; | |
1082 endy= endface->uv[endcorner][1]; | |
1083 firstm= (endy-starty)/(endx-startx); | |
1084 firstb= starty-(firstm*startx); | |
1085 secondm= -1.0f/firstm; | |
1086 if(startx == endx) IsVertical_check= startx; | |
1087 if(starty == endy) IsHorizontal_check= starty; | |
1088 } | |
1089 for(efa= em->faces.first; efa; efa= efa->next) { /* for
each face */ | |
1090 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); /* get face */ | |
1091 if(uvedit_face_visible(scene, ima, efa, tf)) { /
* if you can see it */ | |
1092 if(uvedit_face_selected(scene, efa, tf))
{ /* if the face is selected, get out now! */ | |
1093 pass= 4; | |
1094 break; | |
1095 } | |
1096 for(i= 0; (i < 3 || (i == 3 && efa->v4))
; i++) { /* for each point of the face */ | |
1097 itmpl= (*(&efa->v1 + i))->tmp.l;
/* get unique name for points */ | |
1098 if(pass == 3) { /* move */ | |
1099 if(uvedit_uv_selected(sc
ene, efa, tf, i)) { | |
1100 if(!(itmpl == st
arttmpl || itmpl == endtmpl)) { | |
1101 if(IsVer
tical_check != -1) tf->uv[i][0]= IsVertical_check; | |
1102 if(IsHor
izontal_check != -1) tf->uv[i][1]= IsHorizontal_check; | |
1103 if((IsVe
rtical_check == -1) && (IsHorizontal_check == -1)) { | |
1104
midx= tf->uv[i][0]; | |
1105
midy= tf->uv[i][1]; | |
1106
if(tool == 's') { | |
1107
secondb= midy-(secondm*midx); | |
1108
midmovedx= (secondb-firstb)/(firstm-secondm); | |
1109
midmovedy= (secondm*midmovedx)+secondb; | |
1110
tf->uv[i][0]= midmovedx; | |
1111
tf->uv[i][1]= midmovedy; | |
1112
} | |
1113
else if(tool == 't') { | |
1114
tf->uv[i][0]= (midy-firstb)/firstm; /* midmovedx */ | |
1115
} | |
1116
else if(tool == 'u') { | |
1117
tf->uv[i][1]= (firstm*midx)+firstb; /* midmovedy */ | |
1118
} | |
1119 } | |
1120 } | |
1121 } | |
1122 } | |
1123 else { | |
1124 for(j= 0; (j < 3 || (j =
= 3 && efa->v4)); j++) { /* also for each point on the face */ | |
1125 jtmpl= (*(&efa->
v1 + j))->tmp.l; | |
1126 if(i != j && (!e
fa->v4 || ABS(i-j) != 2)) { /* if the points are connected */ | |
1127 /* quad
(0,1,2,3) 0,1 0,3 1,0 1,2 2,1 2,3 3,0 3,2 | |
1128 * trian
gle (0,1,2) 0,1 0,2 1,0 1,2 2,0 2,1 */ | |
1129 if(uvedi
t_uv_selected(scene, efa, tf, i) && uvedit_uv_selected(scene, efa, tf, j)) { | |
1130
/* if the edge is selected */ | |
1131
if(pass == 1) { /* if finding first endpoint */ | |
1132
if(starttmpl == -1) { /* if the first endpoint isn't found yet */ | |
1133
starttmpl= itmpl; /* set unique name for endpoint */ | |
1134
connectedtostarttmpl= jtmpl; | |
1135
/* get point that endpoint is connected to */ | |
1136
startface= tf; /* get face it's on */ | |
1137
startcorner= i; /* what corner of the face? */ | |
1138
startefa= efa; | |
1139
efa= em->faces.first; | |
1140
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
1141
i= -1; | |
1142
break; | |
1143
} | |
1144
if(starttmpl == itmpl && jtmpl != connectedtostarttmpl) { | |
1145
starttmpl= -1; /* not an endpoint */ | |
1146
efa= startefa; | |
1147
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
1148
i= startcorner; | |
1149
break; | |
1150
} | |
1151
} | |
1152
else if(pass == 2) { /* if finding second endpoint */ | |
1153
if(endtmpl == -1 && itmpl != starttmpl) { | |
1154
endtmpl= itmpl; | |
1155
connectedtoendtmpl= jtmpl; | |
1156
endface= tf; | |
1157
endcorner= i; | |
1158
endefa= efa; | |
1159
efa= em->faces.first; | |
1160
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
1161
i= -1; | |
1162
break; | |
1163
} | |
1164
if(endtmpl == itmpl && jtmpl != connectedtoendtmpl) { | |
1165
endtmpl= -1; | |
1166
efa= endefa; | |
1167
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
1168
i= endcorner; | |
1169
break; | |
1170
} | |
1171
} | |
1172 } | |
1173 } | |
1174 } | |
1175 } | |
1176 } | |
1177 } | |
1178 } | |
1179 if(pass == 2 && (starttmpl == -1 || endtmpl == -1)) { | |
1180 /* if endpoints aren't found */ | |
1181 pass=4; | |
1182 } | |
1183 } | |
1184 } | |
1185 | |
1186 uvedit_live_unwrap_update(sima, scene, obedit); | |
1187 DAG_id_tag_update(obedit->data, 0); | |
1188 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | |
1189 | |
1190 BKE_mesh_end_editmesh(obedit->data, em); | |
1191 } | |
1192 | |
1193 static int align_exec(bContext *C, wmOperator *op) | |
1194 { | |
1195 weld_align_uv(C, RNA_enum_get(op->ptr, "axis")); | |
1196 | |
1197 return OPERATOR_FINISHED; | |
1198 } | |
1199 | |
1200 static void UV_OT_align(wmOperatorType *ot) | |
1201 { | |
1202 static EnumPropertyItem axis_items[] = { | |
1203 {'s', "ALIGN_S", 0, "Straighten", "Align UVs along the line defi
ned by the endpoints"}, | |
1204 {'t', "ALIGN_T", 0, "Straighten X", "Align UVs along the line de
fined by the endpoints along the X axis"}, | |
1205 {'u', "ALIGN_U", 0, "Straighten Y", "Align UVs along the line de
fined by the endpoints along the Y axis"}, | |
1206 {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the a
xis on which there is most alignment already"}, | |
1207 {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"}, | |
1208 {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"}, | |
1209 {0, NULL, 0, NULL, NULL}}; | |
1210 | |
1211 /* identifiers */ | |
1212 ot->name= "Align"; | |
1213 ot->description= "Align selected UV vertices to an axis"; | |
1214 ot->idname= "UV_OT_align"; | |
1215 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1216 ········ | |
1217 /* api callbacks */ | |
1218 ot->exec= align_exec; | |
1219 ot->poll= ED_operator_image_active; /* requires space image */; | |
1220 | |
1221 /* properties */ | |
1222 RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align U
V locations on."); | |
1223 } | |
1224 | |
1225 /* ******************** weld operator **************** */ | |
1226 | |
1227 static int weld_exec(bContext *C, wmOperator *UNUSED(op)) | |
1228 { | |
1229 weld_align_uv(C, 'w'); | |
1230 | |
1231 return OPERATOR_FINISHED; | |
1232 } | |
1233 | |
1234 static void UV_OT_weld(wmOperatorType *ot) | |
1235 { | |
1236 /* identifiers */ | |
1237 ot->name= "Weld"; | |
1238 ot->description= "Weld selected UV vertices together"; | |
1239 ot->idname= "UV_OT_weld"; | |
1240 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1241 ········ | |
1242 /* api callbacks */ | |
1243 ot->exec= weld_exec; | |
1244 ot->poll= ED_operator_uvedit; | |
1245 } | |
1246 | |
1247 /* ******************** stitch operator **************** */ | |
1248 | |
1249 /* just for averaging UVs */ | |
1250 typedef struct UVVertAverage { | |
1251 float uv[2]; | |
1252 int count; | |
1253 } UVVertAverage; | |
1254 | |
1255 static int stitch_exec(bContext *C, wmOperator *op) | |
1256 { | |
1257 SpaceImage *sima; | |
1258 Scene *scene; | |
1259 Object *obedit; | |
1260 EditMesh *em; | |
1261 EditFace *efa; | |
1262 EditVert *eve; | |
1263 Image *ima; | |
1264 MTFace *tf; | |
1265 | |
1266 scene= CTX_data_scene(C); | |
1267 obedit= CTX_data_edit_object(C); | |
1268 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
1269 ima= CTX_data_edit_image(C); | |
1270 sima= CTX_wm_space_image(C); | |
1271 ········ | |
1272 if(RNA_boolean_get(op->ptr, "use_limit")) { | |
1273 UvVertMap *vmap; | |
1274 UvMapVert *vlist, *iterv; | |
1275 float newuv[2], limit[2]; | |
1276 int a, vtot; | |
1277 | |
1278 limit[0]= RNA_float_get(op->ptr, "limit"); | |
1279 limit[1]= limit[0]; | |
1280 | |
1281 EM_init_index_arrays(em, 0, 0, 1); | |
1282 vmap= EM_make_uv_vert_map(em, 1, 0, limit); | |
1283 | |
1284 if(vmap == NULL) { | |
1285 BKE_mesh_end_editmesh(obedit->data, em); | |
1286 return OPERATOR_CANCELLED; | |
1287 } | |
1288 | |
1289 for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) { | |
1290 vlist= EM_get_uv_map_vert(vmap, a); | |
1291 | |
1292 while(vlist) { | |
1293 newuv[0]= 0; newuv[1]= 0; | |
1294 vtot= 0; | |
1295 | |
1296 for(iterv=vlist; iterv; iterv=iterv->next) { | |
1297 if((iterv != vlist) && iterv->separate) | |
1298 break; | |
1299 | |
1300 efa = EM_get_face_for_index(iterv->f); | |
1301 tf = CustomData_em_get(&em->fdata, efa->
data, CD_MTFACE); | |
1302 ········································ | |
1303 if(uvedit_uv_selected(scene, efa, tf, it
erv->tfindex)) { | |
1304 newuv[0] += tf->uv[iterv->tfinde
x][0]; | |
1305 newuv[1] += tf->uv[iterv->tfinde
x][1]; | |
1306 vtot++; | |
1307 } | |
1308 } | |
1309 | |
1310 if(vtot > 1) { | |
1311 newuv[0] /= vtot; newuv[1] /= vtot; | |
1312 | |
1313 for(iterv=vlist; iterv; iterv=iterv->nex
t) { | |
1314 if((iterv != vlist) && iterv->se
parate) | |
1315 break; | |
1316 | |
1317 efa = EM_get_face_for_index(iter
v->f); | |
1318 tf = CustomData_em_get(&em->fdat
a, efa->data, CD_MTFACE); | |
1319 | |
1320 if(uvedit_uv_selected(scene, efa
, tf, iterv->tfindex)) { | |
1321 tf->uv[iterv->tfindex][0
]= newuv[0]; | |
1322 tf->uv[iterv->tfindex][1
]= newuv[1]; | |
1323 } | |
1324 } | |
1325 } | |
1326 | |
1327 vlist= iterv; | |
1328 } | |
1329 } | |
1330 | |
1331 EM_free_uv_vert_map(vmap); | |
1332 EM_free_index_arrays(); | |
1333 } | |
1334 else { | |
1335 UVVertAverage *uv_average, *uvav; | |
1336 int count; | |
1337 | |
1338 // index and count verts | |
1339 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) | |
1340 eve->tmp.l = count; | |
1341 ················ | |
1342 uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch"); | |
1343 ················ | |
1344 // gather uv averages per vert | |
1345 for(efa= em->faces.first; efa; efa= efa->next) { | |
1346 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1347 | |
1348 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1349 if(uvedit_uv_selected(scene, efa, tf, 0)) { | |
1350 uvav = uv_average + efa->v1->tmp.l; | |
1351 uvav->count++; | |
1352 uvav->uv[0] += tf->uv[0][0]; | |
1353 uvav->uv[1] += tf->uv[0][1]; | |
1354 } | |
1355 | |
1356 if(uvedit_uv_selected(scene, efa, tf, 1)) { | |
1357 uvav = uv_average + efa->v2->tmp.l; | |
1358 uvav->count++; | |
1359 uvav->uv[0] += tf->uv[1][0]; | |
1360 uvav->uv[1] += tf->uv[1][1]; | |
1361 } | |
1362 | |
1363 if(uvedit_uv_selected(scene, efa, tf, 2)) { | |
1364 uvav = uv_average + efa->v3->tmp.l; | |
1365 uvav->count++; | |
1366 uvav->uv[0] += tf->uv[2][0]; | |
1367 uvav->uv[1] += tf->uv[2][1]; | |
1368 } | |
1369 | |
1370 if(efa->v4 && uvedit_uv_selected(scene, efa, tf,
3)) { | |
1371 uvav = uv_average + efa->v4->tmp.l; | |
1372 uvav->count++; | |
1373 uvav->uv[0] += tf->uv[3][0]; | |
1374 uvav->uv[1] += tf->uv[3][1]; | |
1375 } | |
1376 } | |
1377 } | |
1378 ················ | |
1379 // apply uv welding | |
1380 for(efa= em->faces.first; efa; efa= efa->next) { | |
1381 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1382 | |
1383 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1384 if(uvedit_uv_selected(scene, efa, tf, 0)) { | |
1385 uvav = uv_average + efa->v1->tmp.l; | |
1386 tf->uv[0][0] = uvav->uv[0]/uvav->count; | |
1387 tf->uv[0][1] = uvav->uv[1]/uvav->count; | |
1388 } | |
1389 | |
1390 if(uvedit_uv_selected(scene, efa, tf, 1)) { | |
1391 uvav = uv_average + efa->v2->tmp.l; | |
1392 tf->uv[1][0] = uvav->uv[0]/uvav->count; | |
1393 tf->uv[1][1] = uvav->uv[1]/uvav->count; | |
1394 } | |
1395 | |
1396 if(uvedit_uv_selected(scene, efa, tf, 2)) { | |
1397 uvav = uv_average + efa->v3->tmp.l; | |
1398 tf->uv[2][0] = uvav->uv[0]/uvav->count; | |
1399 tf->uv[2][1] = uvav->uv[1]/uvav->count; | |
1400 } | |
1401 | |
1402 if(efa->v4 && uvedit_uv_selected(scene, efa, tf,
3)) { | |
1403 uvav = uv_average + efa->v4->tmp.l; | |
1404 tf->uv[3][0] = uvav->uv[0]/uvav->count; | |
1405 tf->uv[3][1] = uvav->uv[1]/uvav->count; | |
1406 } | |
1407 } | |
1408 } | |
1409 | |
1410 MEM_freeN(uv_average); | |
1411 } | |
1412 | |
1413 uvedit_live_unwrap_update(sima, scene, obedit); | |
1414 DAG_id_tag_update(obedit->data, 0); | |
1415 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | |
1416 | |
1417 BKE_mesh_end_editmesh(obedit->data, em); | |
1418 return OPERATOR_FINISHED; | |
1419 } | |
1420 | |
1421 static void UV_OT_stitch(wmOperatorType *ot) | |
1422 { | |
1423 /* identifiers */ | |
1424 ot->name= "Stitch"; | |
1425 ot->description= "Stitch selected UV vertices by proximity"; | |
1426 ot->idname= "UV_OT_stitch"; | |
1427 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1428 ········ | |
1429 /* api callbacks */ | |
1430 ot->exec= stitch_exec; | |
1431 ot->poll= ED_operator_uvedit; | |
1432 | |
1433 /* properties */ | |
1434 RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs withi
n a specified limit distance."); | |
1435 RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit d
istance in normalized coordinates.", -FLT_MAX, FLT_MAX); | |
1436 } | |
1437 | |
1438 /* ******************** (de)select all operator **************** */ | |
1439 | |
1440 static int select_all_exec(bContext *C, wmOperator *op) | |
1441 { | |
1442 Scene *scene; | |
1443 ToolSettings *ts; | |
1444 Object *obedit; | |
1445 EditMesh *em; | |
1446 EditFace *efa; | |
1447 Image *ima; | |
1448 MTFace *tf; | |
1449 int action = RNA_enum_get(op->ptr, "action"); | |
1450 ········ | |
1451 scene= CTX_data_scene(C); | |
1452 ts= CTX_data_tool_settings(C); | |
1453 obedit= CTX_data_edit_object(C); | |
1454 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
1455 ima= CTX_data_edit_image(C); | |
1456 ········ | |
1457 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
1458 switch (action) { | |
1459 case SEL_TOGGLE: | |
1460 EM_toggle_select_all(em); | |
1461 break; | |
1462 case SEL_SELECT: | |
1463 EM_select_all(em); | |
1464 break; | |
1465 case SEL_DESELECT: | |
1466 EM_deselect_all(em); | |
1467 break; | |
1468 case SEL_INVERT: | |
1469 EM_select_swap(em); | |
1470 break; | |
1471 } | |
1472 } | |
1473 else { | |
1474 | |
1475 if (action == SEL_TOGGLE) { | |
1476 action = SEL_SELECT; | |
1477 for(efa= em->faces.first; efa; efa= efa->next) { | |
1478 const char select_flag= efa->v4 ? (TF_SEL1|TF_SE
L2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
1479 tf = CustomData_em_get(&em->fdata, efa->data, CD
_MTFACE); | |
1480 | |
1481 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1482 if(tf->flag & select_flag) { | |
1483 action = SEL_DESELECT; | |
1484 break; | |
1485 } | |
1486 } | |
1487 } | |
1488 } | |
1489 ········ | |
1490 for(efa= em->faces.first; efa; efa= efa->next) { | |
1491 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
; | |
1492 | |
1493 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1494 const char select_flag= efa->v4 ? (TF_SEL1|TF_SE
L2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
1495 | |
1496 switch (action) { | |
1497 case SEL_SELECT: | |
1498 tf->flag |= select_flag; | |
1499 break; | |
1500 case SEL_DESELECT: | |
1501 tf->flag &= ~select_flag; | |
1502 break; | |
1503 case SEL_INVERT: | |
1504 tf->flag ^= select_flag; | |
1505 break; | |
1506 } | |
1507 } | |
1508 } | |
1509 } | |
1510 | |
1511 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
1512 | |
1513 BKE_mesh_end_editmesh(obedit->data, em); | |
1514 return OPERATOR_FINISHED; | |
1515 } | |
1516 | |
1517 static void UV_OT_select_all(wmOperatorType *ot) | |
1518 { | |
1519 /* identifiers */ | |
1520 ot->name= "Select or Deselect All"; | |
1521 ot->description= "Change selection of all UV vertices"; | |
1522 ot->idname= "UV_OT_select_all"; | |
1523 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1524 ········ | |
1525 /* api callbacks */ | |
1526 ot->exec= select_all_exec; | |
1527 ot->poll= ED_operator_uvedit; | |
1528 | |
1529 WM_operator_properties_select_all(ot); | |
1530 } | |
1531 | |
1532 /* ******************** mouse select operator **************** */ | |
1533 | |
1534 static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], floa
t *uv, int sticky) | |
1535 { | |
1536 int i; | |
1537 | |
1538 /* this function test if some vertex needs to selected | |
1539 * in addition to the existing ones due to sticky select */ | |
1540 if(sticky == SI_STICKY_DISABLE) | |
1541 return 0; | |
1542 | |
1543 for(i=0; i<4; i++) { | |
1544 if(hitv[i] == v) { | |
1545 if(sticky == SI_STICKY_LOC) { | |
1546 if(fabsf(hituv[i][0]-uv[0]) < limit[0] && fabsf(
hituv[i][1]-uv[1]) < limit[1]) | |
1547 return 1; | |
1548 } | |
1549 else if(sticky == SI_STICKY_VERTEX) | |
1550 return 1; | |
1551 } | |
1552 } | |
1553 | |
1554 return 0; | |
1555 } | |
1556 | |
1557 static int mouse_select(bContext *C, float co[2], int extend, int loop) | |
1558 { | |
1559 SpaceImage *sima= CTX_wm_space_image(C); | |
1560 Scene *scene= CTX_data_scene(C); | |
1561 ToolSettings *ts= CTX_data_tool_settings(C); | |
1562 Object *obedit= CTX_data_edit_object(C); | |
1563 Image *ima= CTX_data_edit_image(C); | |
1564 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
1565 EditFace *efa; | |
1566 MTFace *tf; | |
1567 NearestHit hit; | |
1568 int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert; | |
1569 int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when
selection sync is enabled */ | |
1570 float limit[2], *hituv[4], penalty[2]; | |
1571 | |
1572 /* notice 'limit' is the same no matter the zoom level, since this is li
ke | |
1573 * remove doubles and could annoying if it joined points when zoomed out
. | |
1574 * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert
and | |
1575 * shift-selecting can consider an adjacent point close enough to add to | |
1576 * the selection rather than de-selecting the closest. */ | |
1577 | |
1578 uvedit_pixel_to_float(sima, limit, 0.05f); | |
1579 uvedit_pixel_to_float(sima, penalty, 5.0f / sima->zoom); | |
1580 | |
1581 /* retrieve operation mode */ | |
1582 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
1583 sync= 1; | |
1584 | |
1585 if(ts->selectmode & SCE_SELECT_FACE) | |
1586 selectmode= UV_SELECT_FACE; | |
1587 else if(ts->selectmode & SCE_SELECT_EDGE) | |
1588 selectmode= UV_SELECT_EDGE; | |
1589 else | |
1590 selectmode= UV_SELECT_VERTEX; | |
1591 | |
1592 sticky= SI_STICKY_DISABLE; | |
1593 } | |
1594 else { | |
1595 sync= 0; | |
1596 selectmode= ts->uv_selectmode; | |
1597 sticky= (sima)? sima->sticky: 1; | |
1598 } | |
1599 | |
1600 /* find nearest element */ | |
1601 if(loop) { | |
1602 /* find edge */ | |
1603 find_nearest_uv_edge(scene, ima, em, co, &hit); | |
1604 if(hit.efa == NULL) { | |
1605 BKE_mesh_end_editmesh(obedit->data, em); | |
1606 return OPERATOR_CANCELLED; | |
1607 } | |
1608 } | |
1609 else if(selectmode == UV_SELECT_VERTEX) { | |
1610 /* find vertex */ | |
1611 find_nearest_uv_vert(scene, ima, em, co, penalty, &hit); | |
1612 if(hit.efa == NULL) { | |
1613 BKE_mesh_end_editmesh(obedit->data, em); | |
1614 return OPERATOR_CANCELLED; | |
1615 } | |
1616 | |
1617 /* mark 1 vertex as being hit */ | |
1618 for(i=0; i<4; i++) | |
1619 hitv[i]= 0xFFFFFFFF; | |
1620 | |
1621 hitv[hit.uv]= hit.vert; | |
1622 hituv[hit.uv]= hit.tf->uv[hit.uv]; | |
1623 } | |
1624 else if(selectmode == UV_SELECT_EDGE) { | |
1625 /* find edge */ | |
1626 find_nearest_uv_edge(scene, ima, em, co, &hit); | |
1627 if(hit.efa == NULL) { | |
1628 BKE_mesh_end_editmesh(obedit->data, em); | |
1629 return OPERATOR_CANCELLED; | |
1630 } | |
1631 | |
1632 /* mark 2 edge vertices as being hit */ | |
1633 for(i=0; i<4; i++) | |
1634 hitv[i]= 0xFFFFFFFF; | |
1635 | |
1636 nvert= (hit.efa->v4)? 4: 3; | |
1637 | |
1638 hitv[hit.edge]= hit.vert; | |
1639 hitv[(hit.edge+1)%nvert]= hit.vert2; | |
1640 hituv[hit.edge]= hit.tf->uv[hit.edge]; | |
1641 hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert]; | |
1642 } | |
1643 else if(selectmode == UV_SELECT_FACE) { | |
1644 /* find face */ | |
1645 find_nearest_uv_face(scene, ima, em, co, &hit); | |
1646 if(hit.efa == NULL) { | |
1647 BKE_mesh_end_editmesh(obedit->data, em); | |
1648 return OPERATOR_CANCELLED; | |
1649 } | |
1650 ················ | |
1651 /* make active */ | |
1652 EM_set_actFace(em, hit.efa); | |
1653 | |
1654 /* mark all face vertices as being hit */ | |
1655 for(i=0; i<4; i++) | |
1656 hituv[i]= hit.tf->uv[i]; | |
1657 | |
1658 hitv[0]= hit.efa->v1->tmp.l; | |
1659 hitv[1]= hit.efa->v2->tmp.l; | |
1660 hitv[2]= hit.efa->v3->tmp.l; | |
1661 ················ | |
1662 if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l; | |
1663 else hitv[3]= 0xFFFFFFFF; | |
1664 } | |
1665 else if(selectmode == UV_SELECT_ISLAND) { | |
1666 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); | |
1667 | |
1668 if(hit.efa==NULL) { | |
1669 BKE_mesh_end_editmesh(obedit->data, em); | |
1670 return OPERATOR_CANCELLED; | |
1671 } | |
1672 } | |
1673 else { | |
1674 BKE_mesh_end_editmesh(obedit->data, em); | |
1675 return OPERATOR_CANCELLED; | |
1676 } | |
1677 | |
1678 /* do selection */ | |
1679 if(loop) { | |
1680 flush= select_edgeloop(scene, ima, em, &hit, limit, extend); | |
1681 } | |
1682 else if(selectmode == UV_SELECT_ISLAND) { | |
1683 select_linked(scene, ima, em, limit, &hit, extend); | |
1684 } | |
1685 else if(extend) { | |
1686 if(selectmode == UV_SELECT_VERTEX) { | |
1687 /* (de)select uv vertex */ | |
1688 if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) { | |
1689 uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.u
v); | |
1690 select= 0; | |
1691 } | |
1692 else { | |
1693 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv)
; | |
1694 select= 1; | |
1695 } | |
1696 flush = 1; | |
1697 } | |
1698 else if(selectmode == UV_SELECT_EDGE) { | |
1699 /* (de)select edge */ | |
1700 if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge
)) { | |
1701 uvedit_edge_deselect(scene, hit.efa, hit.tf, hit
.edge); | |
1702 select= 0; | |
1703 } | |
1704 else { | |
1705 uvedit_edge_select(scene, hit.efa, hit.tf, hit.e
dge); | |
1706 select= 1; | |
1707 } | |
1708 flush = 1; | |
1709 } | |
1710 else if(selectmode == UV_SELECT_FACE) { | |
1711 /* (de)select face */ | |
1712 if(uvedit_face_selected(scene, hit.efa, hit.tf)) { | |
1713 uvedit_face_deselect(scene, hit.efa, hit.tf); | |
1714 select= 0; | |
1715 } | |
1716 else { | |
1717 uvedit_face_select(scene, hit.efa, hit.tf); | |
1718 select= 1; | |
1719 } | |
1720 flush = -1; | |
1721 } | |
1722 | |
1723 /* (de)select sticky uv nodes */ | |
1724 if(sticky != SI_STICKY_DISABLE) { | |
1725 EditVert *ev; | |
1726 ························ | |
1727 for(a=0, ev=em->verts.first; ev; ev = ev->next, a++) | |
1728 ev->tmp.l = a; | |
1729 ························ | |
1730 /* deselect */ | |
1731 if(select==0) { | |
1732 for(efa= em->faces.first; efa; efa= efa->next) { | |
1733 tf= CustomData_em_get(&em->fdata, efa->d
ata, CD_MTFACE); | |
1734 | |
1735 if(uvedit_face_visible(scene, ima, efa,
tf)) { | |
1736 if(sticky_select(limit, hitv, ef
a->v1->tmp.l, hituv, tf->uv[0], sticky)) | |
1737 uvedit_uv_deselect(scene
, efa, tf, 0); | |
1738 if(sticky_select(limit, hitv, ef
a->v2->tmp.l, hituv, tf->uv[1], sticky)) | |
1739 uvedit_uv_deselect(scene
, efa, tf, 1); | |
1740 if(sticky_select(limit, hitv, ef
a->v3->tmp.l, hituv, tf->uv[2], sticky)) | |
1741 uvedit_uv_deselect(scene
, efa, tf, 2); | |
1742 if(efa->v4) | |
1743 if(sticky_select(limit,
hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) | |
1744 uvedit_uv_desele
ct(scene, efa, tf, 3); | |
1745 } | |
1746 } | |
1747 flush = -1; | |
1748 } | |
1749 /* select */ | |
1750 else { | |
1751 for(efa= em->faces.first; efa; efa= efa->next) { | |
1752 tf= CustomData_em_get(&em->fdata, efa->d
ata, CD_MTFACE); | |
1753 | |
1754 if(uvedit_face_visible(scene, ima, efa,
tf)) { | |
1755 if(sticky_select(limit, hitv, ef
a->v1->tmp.l, hituv, tf->uv[0], sticky)) | |
1756 uvedit_uv_select(scene,
efa, tf, 0); | |
1757 if(sticky_select(limit, hitv, ef
a->v2->tmp.l, hituv, tf->uv[1], sticky)) | |
1758 uvedit_uv_select(scene,
efa, tf, 1); | |
1759 if(sticky_select(limit, hitv, ef
a->v3->tmp.l, hituv, tf->uv[2], sticky)) | |
1760 uvedit_uv_select(scene,
efa, tf, 2); | |
1761 if(efa->v4) | |
1762 if(sticky_select(limit,
hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) | |
1763 uvedit_uv_select
(scene, efa, tf, 3); | |
1764 } | |
1765 } | |
1766 ································ | |
1767 flush = 1; | |
1768 }······················· | |
1769 } | |
1770 } | |
1771 else { | |
1772 /* deselect all */ | |
1773 for(efa= em->faces.first; efa; efa= efa->next) { | |
1774 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
1775 uvedit_face_deselect(scene, efa, tf); | |
1776 } | |
1777 | |
1778 if(selectmode == UV_SELECT_VERTEX) { | |
1779 /* select vertex */ | |
1780 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv); | |
1781 flush= 1; | |
1782 } | |
1783 else if(selectmode == UV_SELECT_EDGE) { | |
1784 /* select edge */ | |
1785 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge); | |
1786 flush= 1; | |
1787 } | |
1788 else if(selectmode == UV_SELECT_FACE) { | |
1789 /* select face */ | |
1790 uvedit_face_select(scene, hit.efa, hit.tf); | |
1791 } | |
1792 | |
1793 /* select sticky uvs */ | |
1794 if(sticky != SI_STICKY_DISABLE) { | |
1795 for(efa= em->faces.first; efa; efa= efa->next) { | |
1796 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); | |
1797 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
1798 if(sticky == SI_STICKY_DISABLE) continue
; | |
1799 | |
1800 if(sticky_select(limit, hitv, efa->v1->t
mp.l, hituv, tf->uv[0], sticky)) | |
1801 uvedit_uv_select(scene, efa, tf,
0); | |
1802 if(sticky_select(limit, hitv, efa->v2->t
mp.l, hituv, tf->uv[1], sticky)) | |
1803 uvedit_uv_select(scene, efa, tf,
1); | |
1804 if(sticky_select(limit, hitv, efa->v3->t
mp.l, hituv, tf->uv[2], sticky)) | |
1805 uvedit_uv_select(scene, efa, tf,
2); | |
1806 if(efa->v4) | |
1807 if(sticky_select(limit, hitv, ef
a->v4->tmp.l, hituv, tf->uv[3], sticky)) | |
1808 uvedit_uv_select(scene,
efa, tf, 3); | |
1809 | |
1810 flush= 1; | |
1811 } | |
1812 } | |
1813 } | |
1814 } | |
1815 ········ | |
1816 if(sync) { | |
1817 /* flush for mesh selection */ | |
1818 if(ts->selectmode != SCE_SELECT_FACE) { | |
1819 if(flush==1) EM_select_flush(em); | |
1820 else if(flush==-1) EM_deselect_flush(em); | |
1821 } | |
1822 } | |
1823 ········ | |
1824 DAG_id_tag_update(obedit->data, 0); | |
1825 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
1826 ········ | |
1827 BKE_mesh_end_editmesh(obedit->data, em); | |
1828 return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED; | |
1829 } | |
1830 | |
1831 static int select_exec(bContext *C, wmOperator *op) | |
1832 { | |
1833 float co[2]; | |
1834 int extend, loop; | |
1835 | |
1836 RNA_float_get_array(op->ptr, "location", co); | |
1837 extend= RNA_boolean_get(op->ptr, "extend"); | |
1838 loop= 0; | |
1839 | |
1840 return mouse_select(C, co, extend, loop); | |
1841 } | |
1842 | |
1843 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1844 { | |
1845 ARegion *ar= CTX_wm_region(C); | |
1846 float co[2]; | |
1847 | |
1848 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0
], &co[1]); | |
1849 RNA_float_set_array(op->ptr, "location", co); | |
1850 | |
1851 return select_exec(C, op); | |
1852 } | |
1853 | |
1854 static void UV_OT_select(wmOperatorType *ot) | |
1855 { | |
1856 /* identifiers */ | |
1857 ot->name= "Select"; | |
1858 ot->description= "Select UV vertices"; | |
1859 ot->idname= "UV_OT_select"; | |
1860 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1861 ········ | |
1862 /* api callbacks */ | |
1863 ot->exec= select_exec; | |
1864 ot->invoke= select_invoke; | |
1865 ot->poll= ED_operator_image_active; /* requires space image */; | |
1866 | |
1867 /* properties */ | |
1868 RNA_def_boolean(ot->srna, "extend", 0, | |
1869 "Extend", "Extend selection rather than clearing the existing se
lection."); | |
1870 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, | |
1871 "Location", "Mouse location in normalized coordinates, 0.0 to 1.
0 is within the image bounds.", -100.0f, 100.0f); | |
1872 } | |
1873 | |
1874 /* ******************** loop select operator **************** */ | |
1875 | |
1876 static int select_loop_exec(bContext *C, wmOperator *op) | |
1877 { | |
1878 float co[2]; | |
1879 int extend, loop; | |
1880 | |
1881 RNA_float_get_array(op->ptr, "location", co); | |
1882 extend= RNA_boolean_get(op->ptr, "extend"); | |
1883 loop= 1; | |
1884 | |
1885 return mouse_select(C, co, extend, loop); | |
1886 } | |
1887 | |
1888 static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1889 { | |
1890 ARegion *ar= CTX_wm_region(C); | |
1891 float co[2]; | |
1892 | |
1893 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0
], &co[1]); | |
1894 RNA_float_set_array(op->ptr, "location", co); | |
1895 | |
1896 return select_loop_exec(C, op); | |
1897 } | |
1898 | |
1899 static void UV_OT_select_loop(wmOperatorType *ot) | |
1900 { | |
1901 /* identifiers */ | |
1902 ot->name= "Loop Select"; | |
1903 ot->description= "Select a loop of connected UV vertices"; | |
1904 ot->idname= "UV_OT_select_loop"; | |
1905 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1906 ········ | |
1907 /* api callbacks */ | |
1908 ot->exec= select_loop_exec; | |
1909 ot->invoke= select_loop_invoke; | |
1910 ot->poll= ED_operator_image_active; /* requires space image */; | |
1911 | |
1912 /* properties */ | |
1913 RNA_def_boolean(ot->srna, "extend", 0, | |
1914 "Extend", "Extend selection rather than clearing the existing se
lection."); | |
1915 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, | |
1916 "Location", "Mouse location in normalized coordinates, 0.0 to 1.
0 is within the image bounds.", -100.0f, 100.0f); | |
1917 } | |
1918 | |
1919 /* ******************** linked select operator **************** */ | |
1920 | |
1921 static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i
nt pick) | |
1922 { | |
1923 SpaceImage *sima= CTX_wm_space_image(C); | |
1924 Scene *scene= CTX_data_scene(C); | |
1925 ToolSettings *ts= CTX_data_tool_settings(C); | |
1926 Object *obedit= CTX_data_edit_object(C); | |
1927 Image *ima= CTX_data_edit_image(C); | |
1928 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
1929 float limit[2]; | |
1930 int extend; | |
1931 | |
1932 NearestHit hit, *hit_p= NULL; | |
1933 | |
1934 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
1935 BKE_report(op->reports, RPT_ERROR, "Can't select linked when syn
c selection is enabled."); | |
1936 BKE_mesh_end_editmesh(obedit->data, em); | |
1937 return OPERATOR_CANCELLED; | |
1938 } | |
1939 | |
1940 extend= RNA_boolean_get(op->ptr, "extend"); | |
1941 uvedit_pixel_to_float(sima, limit, 0.05f); | |
1942 | |
1943 if(pick) { | |
1944 float co[2]; | |
1945 | |
1946 if(event) { | |
1947 /* invoke */ | |
1948 ARegion *ar= CTX_wm_region(C); | |
1949 | |
1950 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event
->mval[1], &co[0], &co[1]); | |
1951 RNA_float_set_array(op->ptr, "location", co); | |
1952 } | |
1953 else { | |
1954 /* exec */ | |
1955 RNA_float_get_array(op->ptr, "location", co); | |
1956 } | |
1957 | |
1958 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); | |
1959 hit_p= &hit; | |
1960 } | |
1961 | |
1962 select_linked(scene, ima, em, limit, hit_p, extend); | |
1963 | |
1964 DAG_id_tag_update(obedit->data, 0); | |
1965 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
1966 | |
1967 BKE_mesh_end_editmesh(obedit->data, em); | |
1968 return OPERATOR_FINISHED; | |
1969 } | |
1970 | |
1971 static int select_linked_exec(bContext *C, wmOperator *op) | |
1972 { | |
1973 return select_linked_internal(C, op, NULL, 0); | |
1974 } | |
1975 | |
1976 static void UV_OT_select_linked(wmOperatorType *ot) | |
1977 { | |
1978 /* identifiers */ | |
1979 ot->name= "Select Linked"; | |
1980 ot->description= "Select all UV vertices linked to the active UV map"; | |
1981 ot->idname= "UV_OT_select_linked"; | |
1982 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1983 ········ | |
1984 /* api callbacks */ | |
1985 ot->exec= select_linked_exec; | |
1986 ot->poll= ED_operator_image_active; /* requires space image */ | |
1987 | |
1988 /* properties */ | |
1989 RNA_def_boolean(ot->srna, "extend", 0, | |
1990 "Extend", "Extend selection rather than clearing the existing se
lection."); | |
1991 } | |
1992 | |
1993 static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event
) | |
1994 { | |
1995 return select_linked_internal(C, op, event, 1); | |
1996 } | |
1997 | |
1998 static int select_linked_pick_exec(bContext *C, wmOperator *op) | |
1999 { | |
2000 return select_linked_internal(C, op, NULL, 1); | |
2001 } | |
2002 | |
2003 static void UV_OT_select_linked_pick(wmOperatorType *ot) | |
2004 { | |
2005 /* identifiers */ | |
2006 ot->name= "Select Linked Pick"; | |
2007 ot->description= "Select all UV vertices linked under the mouse"; | |
2008 ot->idname= "UV_OT_select_linked_pick"; | |
2009 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2010 | |
2011 /* api callbacks */ | |
2012 ot->invoke= select_linked_pick_invoke; | |
2013 ot->exec= select_linked_pick_exec; | |
2014 ot->poll= ED_operator_image_active; /* requires space image */; | |
2015 | |
2016 /* properties */ | |
2017 RNA_def_boolean(ot->srna, "extend", 0, | |
2018 "Extend", "Extend selection rather than clearing the existing se
lection."); | |
2019 | |
2020 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, | |
2021 "Location", "Mouse location in normalized coordinates, 0.0 to 1.
0 is within the image bounds.", -100.0f, 100.0f); | |
2022 } | |
2023 | |
2024 /* ******************** unlink selection operator **************** */ | |
2025 | |
2026 static int unlink_selection_exec(bContext *C, wmOperator *op) | |
2027 { | |
2028 Scene *scene= CTX_data_scene(C); | |
2029 ToolSettings *ts= CTX_data_tool_settings(C); | |
2030 Object *obedit= CTX_data_edit_object(C); | |
2031 Image *ima= CTX_data_edit_image(C); | |
2032 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2033 EditFace *efa; | |
2034 MTFace *tf; | |
2035 | |
2036 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
2037 BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when
sync selection is enabled."); | |
2038 BKE_mesh_end_editmesh(obedit->data, em); | |
2039 return OPERATOR_CANCELLED; | |
2040 } | |
2041 ········ | |
2042 for(efa= em->faces.first; efa; efa= efa->next) { | |
2043 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2044 | |
2045 if(uvedit_face_visible(scene, ima, efa, tf)) { | |
2046 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SE
L3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
2047 if(~tf->flag & select_flag) | |
2048 tf->flag &= ~select_flag; | |
2049 | |
2050 } | |
2051 } | |
2052 ········ | |
2053 DAG_id_tag_update(obedit->data, 0); | |
2054 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2055 | |
2056 BKE_mesh_end_editmesh(obedit->data, em); | |
2057 return OPERATOR_FINISHED; | |
2058 } | |
2059 | |
2060 static void UV_OT_unlink_selected(wmOperatorType *ot) | |
2061 { | |
2062 /* identifiers */ | |
2063 ot->name= "Unlink Selection"; | |
2064 ot->description= "Unlink selected UV vertices from active UV map"; | |
2065 ot->idname= "UV_OT_unlink_selected"; | |
2066 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2067 ········ | |
2068 /* api callbacks */ | |
2069 ot->exec= unlink_selection_exec; | |
2070 ot->poll= ED_operator_uvedit; | |
2071 } | |
2072 | |
2073 /* ******************** border select operator **************** */ | |
2074 | |
2075 /* This function sets the selection on tagged faces, need because settings the | |
2076 * selection a face is done in a number of places but it also needs to respect | |
2077 * the sticky modes for the UV verts, so dealing with the sticky modes is best | |
2078 * done in a separate function. | |
2079 *· | |
2080 * De-selects faces that have been tagged on efa->tmp.l. */ | |
2081 | |
2082 static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
ct *obedit, short select) | |
2083 { | |
2084 /* Selecting UV Faces with some modes requires us to change· | |
2085 * the selection in other faces (depending on the sticky mode). | |
2086 *· | |
2087 * This only needs to be done when the Mesh is not used for | |
2088 * selection (so for sticky modes, vertex or location based). */ | |
2089 ········ | |
2090 ToolSettings *ts= CTX_data_tool_settings(C); | |
2091 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2092 EditFace *efa; | |
2093 MTFace *tf; | |
2094 int nverts, i; | |
2095 ········ | |
2096 if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VER
TEX) { | |
2097 /* Tag all verts as untouched, then touch the ones that have a f
ace center | |
2098 * in the loop and select all MTFace UV's that use a touched ver
t. */ | |
2099 EditVert *eve; | |
2100 ················ | |
2101 for(eve= em->verts.first; eve; eve= eve->next) | |
2102 eve->tmp.l = 0; | |
2103 ················ | |
2104 for(efa= em->faces.first; efa; efa= efa->next) { | |
2105 if(efa->tmp.l) { | |
2106 if(efa->v4) | |
2107 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3-
>tmp.l= efa->v4->tmp.l=1; | |
2108 else | |
2109 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3-
>tmp.l= 1; | |
2110 } | |
2111 } | |
2112 | |
2113 /* now select tagged verts */ | |
2114 for(efa= em->faces.first; efa; efa= efa->next) { | |
2115 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE)
;··············· | |
2116 nverts= efa->v4? 4: 3; | |
2117 for(i=0; i<nverts; i++) { | |
2118 if((*(&efa->v1 + i))->tmp.l) { | |
2119 if(select) | |
2120 uvedit_uv_select(scene, efa, tf,
i); | |
2121 else | |
2122 uvedit_uv_deselect(scene, efa, t
f, i); | |
2123 } | |
2124 } | |
2125 } | |
2126 } | |
2127 else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICK
Y_LOC) { | |
2128 EditFace *efa_vlist; | |
2129 MTFace *tf_vlist; | |
2130 UvMapVert *start_vlist=NULL, *vlist_iter; | |
2131 struct UvVertMap *vmap; | |
2132 float limit[2]; | |
2133 unsigned int efa_index; | |
2134 //EditVert *eve; /* removed vert counting for now */· | |
2135 //int a; | |
2136 ················ | |
2137 uvedit_pixel_to_float(sima, limit, 0.05); | |
2138 ················ | |
2139 EM_init_index_arrays(em, 0, 0, 1); | |
2140 vmap= EM_make_uv_vert_map(em, 0, 0, limit); | |
2141 ················ | |
2142 /* verts are numbered above in make_uv_vert_map_EM, make sure th
is stays true! */ | |
2143 /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) | |
2144 eve->tmp.l = a; */ | |
2145 ················ | |
2146 if(vmap == NULL) { | |
2147 BKE_mesh_end_editmesh(obedit->data, em); | |
2148 return; | |
2149 } | |
2150 ················ | |
2151 for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= ef
a->next) { | |
2152 if(efa->tmp.l) { | |
2153 tf = CustomData_em_get(&em->fdata, efa->data, CD
_MTFACE); | |
2154 nverts= efa->v4? 4: 3; | |
2155 | |
2156 for(i=0; i<nverts; i++) { | |
2157 if(select) | |
2158 uvedit_uv_select(scene, efa, tf,
i); | |
2159 else | |
2160 uvedit_uv_deselect(scene, efa, t
f, i); | |
2161 ········································ | |
2162 vlist_iter= EM_get_uv_map_vert(vmap, (*(
&efa->v1 + i))->tmp.l); | |
2163 ········································ | |
2164 while (vlist_iter) { | |
2165 if(vlist_iter->separate) | |
2166 start_vlist = vlist_iter
; | |
2167 ················································ | |
2168 if(efa_index == vlist_iter->f) | |
2169 break; | |
2170 | |
2171 vlist_iter = vlist_iter->next; | |
2172 } | |
2173 ································ | |
2174 vlist_iter = start_vlist; | |
2175 while (vlist_iter) { | |
2176 ················································ | |
2177 if(vlist_iter != start_vlist &&
vlist_iter->separate) | |
2178 break; | |
2179 ················································ | |
2180 if(efa_index != vlist_iter->f) { | |
2181 efa_vlist = EM_get_face_
for_index(vlist_iter->f); | |
2182 tf_vlist = CustomData_em
_get(&em->fdata, efa_vlist->data, CD_MTFACE); | |
2183 ························································ | |
2184 if(select) | |
2185 uvedit_uv_select
(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); | |
2186 else | |
2187 uvedit_uv_desele
ct(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); | |
2188 } | |
2189 vlist_iter = vlist_iter->next; | |
2190 } | |
2191 } | |
2192 } | |
2193 } | |
2194 EM_free_index_arrays(); | |
2195 EM_free_uv_vert_map(vmap); | |
2196 ················ | |
2197 } | |
2198 else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ | |
2199 for(efa= em->faces.first; efa; efa= efa->next) { | |
2200 if(efa->tmp.l) { | |
2201 tf = CustomData_em_get(&em->fdata, efa->data, CD
_MTFACE); | |
2202 if(select) | |
2203 uvedit_face_select(scene, efa, tf); | |
2204 else | |
2205 uvedit_face_deselect(scene, efa, tf); | |
2206 } | |
2207 } | |
2208 } | |
2209 BKE_mesh_end_editmesh(obedit->data, em); | |
2210 } | |
2211 | |
2212 static int border_select_exec(bContext *C, wmOperator *op) | |
2213 { | |
2214 SpaceImage *sima= CTX_wm_space_image(C); | |
2215 Scene *scene= CTX_data_scene(C); | |
2216 ToolSettings *ts= CTX_data_tool_settings(C); | |
2217 Object *obedit= CTX_data_edit_object(C); | |
2218 Image *ima= CTX_data_edit_image(C); | |
2219 ARegion *ar= CTX_wm_region(C); | |
2220 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2221 EditFace *efa; | |
2222 MTFace *tface; | |
2223 rcti rect; | |
2224 rctf rectf; | |
2225 int change, pinned, select, faces; | |
2226 | |
2227 /* get rectangle from operator */ | |
2228 rect.xmin= RNA_int_get(op->ptr, "xmin"); | |
2229 rect.ymin= RNA_int_get(op->ptr, "ymin"); | |
2230 rect.xmax= RNA_int_get(op->ptr, "xmax"); | |
2231 rect.ymax= RNA_int_get(op->ptr, "ymax"); | |
2232 ················ | |
2233 UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &r
ectf.ymin); | |
2234 UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &r
ectf.ymax); | |
2235 | |
2236 /* figure out what to select/deselect */ | |
2237 select= (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT); | |
2238 pinned= RNA_boolean_get(op->ptr, "pinned"); | |
2239 ········ | |
2240 if(ts->uv_flag & UV_SYNC_SELECTION) | |
2241 faces= (ts->selectmode == SCE_SELECT_FACE); | |
2242 else | |
2243 faces= (ts->uv_selectmode == UV_SELECT_FACE); | |
2244 | |
2245 /* do actual selection */ | |
2246 if(faces && !pinned) { | |
2247 /* handle face selection mode */ | |
2248 float cent[2]; | |
2249 | |
2250 change= 0; | |
2251 | |
2252 for(efa= em->faces.first; efa; efa= efa->next) { | |
2253 /* assume not touched */ | |
2254 efa->tmp.l = 0; | |
2255 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFAC
E); | |
2256 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2257 uv_center(tface->uv, cent, efa->v4 != NULL); | |
2258 if(BLI_in_rctf(&rectf, cent[0], cent[1])) { | |
2259 efa->tmp.l = change = 1; | |
2260 } | |
2261 } | |
2262 } | |
2263 | |
2264 /* (de)selects all tagged faces and deals with sticky modes */ | |
2265 if(change) | |
2266 uv_faces_do_sticky(C, sima, scene, obedit, select); | |
2267 } | |
2268 else { | |
2269 /* other selection modes */ | |
2270 change= 1; | |
2271 | |
2272 for(efa= em->faces.first; efa; efa= efa->next) { | |
2273 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFAC
E); | |
2274 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2275 if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION)
) { | |
2276 /* UV_SYNC_SELECTION - can't do pinned s
election */ | |
2277 if(BLI_in_rctf(&rectf, tface->uv[0][0],
tface->uv[0][1])) { | |
2278 if(select) uvedit_uv_select
(scene, efa, tface, 0); | |
2279 else uvedit_uv_desele
ct(scene, efa, tface, 0); | |
2280 } | |
2281 if(BLI_in_rctf(&rectf, tface->uv[1][0],
tface->uv[1][1])) { | |
2282 if(select) uvedit_uv_select
(scene, efa, tface, 1); | |
2283 else uvedit_uv_desele
ct(scene, efa, tface, 1); | |
2284 } | |
2285 if(BLI_in_rctf(&rectf, tface->uv[2][0],
tface->uv[2][1])) { | |
2286 if(select) uvedit_uv_select
(scene, efa, tface, 2); | |
2287 else uvedit_uv_desele
ct(scene, efa, tface, 2); | |
2288 } | |
2289 if(efa->v4 && BLI_in_rctf(&rectf, tface-
>uv[3][0], tface->uv[3][1])) { | |
2290 if(select) uvedit_uv_select
(scene, efa, tface, 3); | |
2291 else uvedit_uv_desele
ct(scene, efa, tface, 3); | |
2292 } | |
2293 } | |
2294 else if(pinned) { | |
2295 if((tface->unwrap & TF_PIN1) &&· | |
2296 BLI_in_rctf(&rectf, tface->uv[0]
[0], tface->uv[0][1])) { | |
2297 ················································ | |
2298 if(select) uvedit_uv_select
(scene, efa, tface, 0); | |
2299 else uvedit_uv_desele
ct(scene, efa, tface, 0); | |
2300 } | |
2301 if((tface->unwrap & TF_PIN2) &&· | |
2302 BLI_in_rctf(&rectf, tface->uv[1]
[0], tface->uv[1][1])) { | |
2303 ················································ | |
2304 if(select) uvedit_uv_select
(scene, efa, tface, 1); | |
2305 else uvedit_uv_desele
ct(scene, efa, tface, 1); | |
2306 } | |
2307 if((tface->unwrap & TF_PIN3) &&· | |
2308 BLI_in_rctf(&rectf, tface->uv[2]
[0], tface->uv[2][1])) { | |
2309 ················································ | |
2310 if(select) uvedit_uv_select
(scene, efa, tface, 2); | |
2311 else uvedit_uv_desele
ct(scene, efa, tface, 2); | |
2312 } | |
2313 if((efa->v4) && (tface->unwrap & TF_PIN4
) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { | |
2314 if(select) uvedit_uv_select
(scene, efa, tface, 3); | |
2315 else uvedit_uv_desele
ct(scene, efa, tface, 3); | |
2316 } | |
2317 } | |
2318 } | |
2319 } | |
2320 } | |
2321 | |
2322 if(change) { | |
2323 /* make sure newly selected vert selection is updated*/ | |
2324 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
2325 if(ts->selectmode != SCE_SELECT_FACE) { | |
2326 if(select) EM_select_flush(em); | |
2327 else EM_deselect_flush(em); | |
2328 } | |
2329 } | |
2330 | |
2331 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2332 ················ | |
2333 BKE_mesh_end_editmesh(obedit->data, em); | |
2334 return OPERATOR_FINISHED; | |
2335 } | |
2336 ········ | |
2337 BKE_mesh_end_editmesh(obedit->data, em); | |
2338 return OPERATOR_CANCELLED; | |
2339 }· | |
2340 | |
2341 static void UV_OT_select_border(wmOperatorType *ot) | |
2342 { | |
2343 /* identifiers */ | |
2344 ot->name= "Border Select"; | |
2345 ot->description= "Select UV vertices using border selection"; | |
2346 ot->idname= "UV_OT_select_border"; | |
2347 ········ | |
2348 /* api callbacks */ | |
2349 ot->invoke= WM_border_select_invoke; | |
2350 ot->exec= border_select_exec; | |
2351 ot->modal= WM_border_select_modal; | |
2352 ot->poll= ED_operator_image_active; /* requires space image */; | |
2353 ot->cancel= WM_border_select_cancel; | |
2354 ········ | |
2355 /* flags */ | |
2356 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2357 ········ | |
2358 /* properties */ | |
2359 RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned U
Vs only."); | |
2360 | |
2361 WM_operator_properties_gesture_border(ot, FALSE); | |
2362 } | |
2363 | |
2364 /* ******************** circle select operator **************** */ | |
2365 | |
2366 static void select_uv_inside_ellipse(Scene *scene, int select, EditFace *efa, MT
Face *tface, int index, float *offset, float *ell, int select_index) | |
2367 { | |
2368 /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ | |
2369 float x, y, r2, *uv; | |
2370 ········ | |
2371 uv= tface->uv[index]; | |
2372 | |
2373 x= (uv[0] - offset[0])*ell[0]; | |
2374 y= (uv[1] - offset[1])*ell[1]; | |
2375 | |
2376 r2 = x*x + y*y; | |
2377 if(r2 < 1.0f) { | |
2378 if(select) uvedit_uv_select(scene, efa, tface, select_index
); | |
2379 else uvedit_uv_deselect(scene, efa, tface, select_index); | |
2380 } | |
2381 } | |
2382 | |
2383 static int circle_select_exec(bContext *C, wmOperator *op) | |
2384 { | |
2385 SpaceImage *sima= CTX_wm_space_image(C); | |
2386 Scene *scene= CTX_data_scene(C); | |
2387 Object *obedit= CTX_data_edit_object(C); | |
2388 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2389 ARegion *ar= CTX_wm_region(C); | |
2390 EditFace *efa; | |
2391 MTFace *tface; | |
2392 int x, y, radius, width, height, select; | |
2393 float zoomx, zoomy, offset[2], ellipse[2]; | |
2394 int gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); | |
2395 | |
2396 /* get operator properties */ | |
2397 select= (gesture_mode == GESTURE_MODAL_SELECT); | |
2398 x= RNA_int_get(op->ptr, "x"); | |
2399 y= RNA_int_get(op->ptr, "y"); | |
2400 radius= RNA_int_get(op->ptr, "radius"); | |
2401 | |
2402 /* compute ellipse size and location, not a circle since we deal | |
2403 * with non square image. ellipse is normalized, r = 1.0. */ | |
2404 ED_space_image_size(sima, &width, &height); | |
2405 ED_space_image_zoom(sima, ar, &zoomx, &zoomy); | |
2406 | |
2407 ellipse[0]= width*zoomx/radius; | |
2408 ellipse[1]= height*zoomy/radius; | |
2409 | |
2410 UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); | |
2411 ········ | |
2412 /* do selection */ | |
2413 for(efa= em->faces.first; efa; efa= efa->next) { | |
2414 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2415 select_uv_inside_ellipse(scene, select, efa, tface, 0, offset, e
llipse, 0); | |
2416 select_uv_inside_ellipse(scene, select, efa, tface, 1, offset, e
llipse, 1); | |
2417 select_uv_inside_ellipse(scene, select, efa, tface, 2, offset, e
llipse, 2); | |
2418 if(efa->v4) | |
2419 select_uv_inside_ellipse(scene, select, efa, tface, 3, o
ffset, ellipse, 3); | |
2420 } | |
2421 | |
2422 if(select) EM_select_flush(em); | |
2423 else EM_deselect_flush(em); | |
2424 | |
2425 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2426 | |
2427 BKE_mesh_end_editmesh(obedit->data, em); | |
2428 return OPERATOR_FINISHED; | |
2429 } | |
2430 | |
2431 static void UV_OT_circle_select(wmOperatorType *ot) | |
2432 { | |
2433 /* identifiers */ | |
2434 ot->name= "Circle Select"; | |
2435 ot->description= "Select UV vertices using circle selection"; | |
2436 ot->idname= "UV_OT_circle_select"; | |
2437 ········ | |
2438 /* api callbacks */ | |
2439 ot->invoke= WM_gesture_circle_invoke; | |
2440 ot->modal= WM_gesture_circle_modal; | |
2441 ot->exec= circle_select_exec; | |
2442 ot->poll= ED_operator_image_active; /* requires space image */; | |
2443 ot->cancel= WM_gesture_circle_cancel; | |
2444 ········ | |
2445 /* flags */ | |
2446 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2447 ········ | |
2448 /* properties */ | |
2449 RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MA
X); | |
2450 RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MA
X); | |
2451 RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_M
IN, INT_MAX); | |
2452 RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode
", "", INT_MIN, INT_MAX); | |
2453 } | |
2454 | |
2455 /* ******************** snap cursor operator **************** */ | |
2456 | |
2457 static void snap_uv_to_pixel(float *uvco, float w, float h) | |
2458 { | |
2459 uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w; | |
2460 uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h; | |
2461 } | |
2462 | |
2463 static void snap_cursor_to_pixels(SpaceImage *sima) | |
2464 { | |
2465 int width= 0, height= 0; | |
2466 | |
2467 ED_space_image_size(sima, &width, &height); | |
2468 snap_uv_to_pixel(sima->cursor, width, height); | |
2469 } | |
2470 | |
2471 static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, Sp
aceImage *sima) | |
2472 { | |
2473 return uvedit_center(scene, ima, obedit, sima->cursor, sima->around); | |
2474 } | |
2475 | |
2476 static int snap_cursor_exec(bContext *C, wmOperator *op) | |
2477 { | |
2478 SpaceImage *sima= CTX_wm_space_image(C); | |
2479 Scene *scene= CTX_data_scene(C); | |
2480 Object *obedit= CTX_data_edit_object(C); | |
2481 Image *ima= CTX_data_edit_image(C); | |
2482 int change= 0; | |
2483 | |
2484 switch(RNA_enum_get(op->ptr, "target")) { | |
2485 case 0: | |
2486 snap_cursor_to_pixels(sima); | |
2487 change= 1; | |
2488 break; | |
2489 case 1: | |
2490 change= snap_cursor_to_selection(scene, ima, obedit, sim
a); | |
2491 break; | |
2492 } | |
2493 | |
2494 if(!change) | |
2495 return OPERATOR_CANCELLED; | |
2496 ········ | |
2497 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, sima); | |
2498 | |
2499 return OPERATOR_FINISHED; | |
2500 } | |
2501 | |
2502 static void UV_OT_snap_cursor(wmOperatorType *ot) | |
2503 { | |
2504 static EnumPropertyItem target_items[] = { | |
2505 {0, "PIXELS", 0, "Pixels", ""}, | |
2506 {1, "SELECTED", 0, "Selected", ""}, | |
2507 {0, NULL, 0, NULL, NULL}}; | |
2508 | |
2509 /* identifiers */ | |
2510 ot->name= "Snap Cursor"; | |
2511 ot->description= "Snap cursor to target type"; | |
2512 ot->idname= "UV_OT_snap_cursor"; | |
2513 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2514 ········ | |
2515 /* api callbacks */ | |
2516 ot->exec= snap_cursor_exec; | |
2517 ot->poll= ED_operator_image_active; /* requires space image */; | |
2518 | |
2519 /* properties */ | |
2520 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to s
nap the selected UV's to."); | |
2521 } | |
2522 | |
2523 /* ******************** snap selection operator **************** */ | |
2524 | |
2525 static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceIma
ge *sima) | |
2526 { | |
2527 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2528 EditFace *efa; | |
2529 MTFace *tface; | |
2530 short change= 0; | |
2531 | |
2532 for(efa= em->faces.first; efa; efa= efa->next) { | |
2533 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2534 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2535 if(uvedit_uv_selected(scene, efa, tface, 0))
VECCOPY2D(tface->uv[0], sima->cursor); | |
2536 if(uvedit_uv_selected(scene, efa, tface, 1))
VECCOPY2D(tface->uv[1], sima->cursor); | |
2537 if(uvedit_uv_selected(scene, efa, tface, 2))
VECCOPY2D(tface->uv[2], sima->cursor); | |
2538 if(efa->v4) | |
2539 if(uvedit_uv_selected(scene, efa, tface, 3))
VECCOPY2D(tface->uv[3], sima->cursor); | |
2540 | |
2541 change= 1; | |
2542 } | |
2543 } | |
2544 | |
2545 BKE_mesh_end_editmesh(obedit->data, em); | |
2546 return change; | |
2547 } | |
2548 | |
2549 static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
dit) | |
2550 { | |
2551 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2552 EditFace *efa; | |
2553 EditVert *eve; | |
2554 MTFace *tface; | |
2555 short change = 0; | |
2556 int count = 0; | |
2557 float *coords; | |
2558 short *usercount, users; | |
2559 ········ | |
2560 /* set all verts to -1 : an unused index*/ | |
2561 for(eve= em->verts.first; eve; eve= eve->next) | |
2562 eve->tmp.l=-1; | |
2563 ········ | |
2564 /* index every vert that has a selected UV using it, but only once so as
to | |
2565 * get unique indices and to count how much to malloc */ | |
2566 for(efa= em->faces.first; efa; efa= efa->next) { | |
2567 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2568 | |
2569 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2570 if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->
tmp.l==-1) efa->v1->tmp.l= count++; | |
2571 if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->
tmp.l==-1) efa->v2->tmp.l= count++; | |
2572 if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->
tmp.l==-1) efa->v3->tmp.l= count++; | |
2573 if(efa->v4) | |
2574 if(uvedit_uv_selected(scene, efa, tface, 3) && e
fa->v4->tmp.l==-1) efa->v4->tmp.l= count++; | |
2575 | |
2576 change = 1; | |
2577 ························ | |
2578 /* optional speedup */ | |
2579 efa->tmp.p = tface; | |
2580 } | |
2581 else | |
2582 efa->tmp.p = NULL; | |
2583 } | |
2584 ········ | |
2585 coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords"); | |
2586 usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts"); | |
2587 ········ | |
2588 /* add all UV coords from visible, unselected UV coords as well as count
ing them to average later */ | |
2589 for(efa= em->faces.first; efa; efa= efa->next) { | |
2590 if((tface=(MTFace *)efa->tmp.p)) { | |
2591 /* is this an unselected UV we can snap to? */ | |
2592 if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, ef
a, tface, 0))) { | |
2593 coords[efa->v1->tmp.l*2] += tface->u
v[0][0]; | |
2594 coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1]; | |
2595 usercount[efa->v1->tmp.l]++; | |
2596 change = 1; | |
2597 } | |
2598 if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, ef
a, tface, 1))) { | |
2599 coords[efa->v2->tmp.l*2] += tface->u
v[1][0]; | |
2600 coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1]; | |
2601 usercount[efa->v2->tmp.l]++; | |
2602 change = 1; | |
2603 } | |
2604 if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, ef
a, tface, 2))) { | |
2605 coords[efa->v3->tmp.l*2] += tface->u
v[2][0]; | |
2606 coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1]; | |
2607 usercount[efa->v3->tmp.l]++; | |
2608 change = 1; | |
2609 } | |
2610 ························ | |
2611 if(efa->v4) { | |
2612 if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(s
cene, efa, tface, 3))) { | |
2613 coords[efa->v4->tmp.l*2] +=
tface->uv[3][0]; | |
2614 coords[(efa->v4->tmp.l*2)+1] += tface->u
v[3][1]; | |
2615 usercount[efa->v4->tmp.l]++; | |
2616 change = 1; | |
2617 } | |
2618 } | |
2619 } | |
2620 } | |
2621 ········ | |
2622 /* no other verts selected, bail out */ | |
2623 if(!change) { | |
2624 MEM_freeN(coords); | |
2625 MEM_freeN(usercount); | |
2626 BKE_mesh_end_editmesh(obedit->data, em); | |
2627 return change; | |
2628 } | |
2629 ········ | |
2630 /* copy the averaged unselected UVs back to the selected UVs */ | |
2631 for(efa= em->faces.first; efa; efa= efa->next) { | |
2632 if((tface=(MTFace *)efa->tmp.p)) { | |
2633 ························ | |
2634 if( uvedit_uv_selected(scene, efa, tface, 0) && | |
2635 efa->v1->tmp.l >= 0 && | |
2636 (users = usercount[efa->v1->tmp.l]) | |
2637 ) { | |
2638 tface->uv[0][0] = coords[efa->v1->tmp.l*2]
/ users; | |
2639 tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1]
/ users; | |
2640 } | |
2641 | |
2642 if( uvedit_uv_selected(scene, efa, tface, 1) && | |
2643 efa->v2->tmp.l >= 0 && | |
2644 (users = usercount[efa->v2->tmp.l]) | |
2645 ) { | |
2646 tface->uv[1][0] = coords[efa->v2->tmp.l*2]
/ users; | |
2647 tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1]
/ users; | |
2648 } | |
2649 ························ | |
2650 if( uvedit_uv_selected(scene, efa, tface, 2) && | |
2651 efa->v3->tmp.l >= 0 && | |
2652 (users = usercount[efa->v3->tmp.l]) | |
2653 ) { | |
2654 tface->uv[2][0] = coords[efa->v3->tmp.l*2]
/ users; | |
2655 tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1]
/ users; | |
2656 } | |
2657 ························ | |
2658 if(efa->v4) { | |
2659 if( uvedit_uv_selected(scene, efa, tface, 3)
&& | |
2660 efa->v4->tmp.l >= 0 && | |
2661 (users = usercount[efa->v4->tmp.
l]) | |
2662 ) { | |
2663 tface->uv[3][0] = coords[efa->v4->tmp.l*
2] / users; | |
2664 tface->uv[3][1] = coords[(efa->v4->tmp.l
*2)+1] / users; | |
2665 } | |
2666 } | |
2667 } | |
2668 } | |
2669 ········ | |
2670 MEM_freeN(coords); | |
2671 MEM_freeN(usercount); | |
2672 | |
2673 BKE_mesh_end_editmesh(obedit->data, em); | |
2674 return change; | |
2675 } | |
2676 | |
2677 static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) | |
2678 { | |
2679 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2680 Image *ima; | |
2681 EditFace *efa; | |
2682 MTFace *tface; | |
2683 int width= 0, height= 0; | |
2684 float w, h; | |
2685 short change = 0; | |
2686 | |
2687 if(!sima) | |
2688 return 0; | |
2689 ········ | |
2690 ima= sima->image; | |
2691 ········ | |
2692 ED_space_image_size(sima, &width, &height); | |
2693 w = (float)width; | |
2694 h = (float)height; | |
2695 ········ | |
2696 for(efa= em->faces.first; efa; efa= efa->next) { | |
2697 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2698 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2699 if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_
pixel(tface->uv[0], w, h); | |
2700 if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_
pixel(tface->uv[1], w, h); | |
2701 if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_
pixel(tface->uv[2], w, h); | |
2702 if(efa->v4) | |
2703 if(uvedit_uv_selected(scene, efa, tface, 3)) sna
p_uv_to_pixel(tface->uv[3], w, h); | |
2704 | |
2705 change = 1; | |
2706 } | |
2707 } | |
2708 | |
2709 BKE_mesh_end_editmesh(obedit->data, em); | |
2710 return change; | |
2711 } | |
2712 | |
2713 static int snap_selection_exec(bContext *C, wmOperator *op) | |
2714 { | |
2715 SpaceImage *sima= CTX_wm_space_image(C); | |
2716 Scene *scene= CTX_data_scene(C); | |
2717 Object *obedit= CTX_data_edit_object(C); | |
2718 Image *ima= CTX_data_edit_image(C); | |
2719 int change= 0; | |
2720 | |
2721 switch(RNA_enum_get(op->ptr, "target")) { | |
2722 case 0: | |
2723 change= snap_uvs_to_pixels(sima, scene, obedit); | |
2724 break; | |
2725 case 1: | |
2726 change= snap_uvs_to_cursor(scene, ima, obedit, sima); | |
2727 break; | |
2728 case 2: | |
2729 change= snap_uvs_to_adjacent_unselected(scene, ima, obed
it); | |
2730 break; | |
2731 } | |
2732 | |
2733 if(!change) | |
2734 return OPERATOR_CANCELLED; | |
2735 | |
2736 uvedit_live_unwrap_update(sima, scene, obedit); | |
2737 DAG_id_tag_update(obedit->data, 0); | |
2738 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | |
2739 | |
2740 return OPERATOR_FINISHED; | |
2741 } | |
2742 | |
2743 static void UV_OT_snap_selected(wmOperatorType *ot) | |
2744 { | |
2745 static EnumPropertyItem target_items[] = { | |
2746 {0, "PIXELS", 0, "Pixels", ""}, | |
2747 {1, "CURSOR", 0, "Cursor", ""}, | |
2748 {2, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""}, | |
2749 {0, NULL, 0, NULL, NULL}}; | |
2750 | |
2751 /* identifiers */ | |
2752 ot->name= "Snap Selection"; | |
2753 ot->description= "Snap selected UV vertices to target type"; | |
2754 ot->idname= "UV_OT_snap_selected"; | |
2755 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2756 ········ | |
2757 /* api callbacks */ | |
2758 ot->exec= snap_selection_exec; | |
2759 ot->poll= ED_operator_image_active; /* requires space image */; | |
2760 | |
2761 /* properties */ | |
2762 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to s
nap the selected UV's to."); | |
2763 } | |
2764 | |
2765 /* ******************** pin operator **************** */ | |
2766 | |
2767 static int pin_exec(bContext *C, wmOperator *op) | |
2768 { | |
2769 Scene *scene= CTX_data_scene(C); | |
2770 Object *obedit= CTX_data_edit_object(C); | |
2771 Image *ima= CTX_data_edit_image(C); | |
2772 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2773 EditFace *efa; | |
2774 MTFace *tface; | |
2775 int clear= RNA_boolean_get(op->ptr, "clear"); | |
2776 ········ | |
2777 for(efa= em->faces.first; efa; efa= efa->next) { | |
2778 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2779 | |
2780 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2781 if(!clear) { | |
2782 if(uvedit_uv_selected(scene, efa, tface, 0)) tfa
ce->unwrap |= TF_PIN1; | |
2783 if(uvedit_uv_selected(scene, efa, tface, 1)) tfa
ce->unwrap |= TF_PIN2; | |
2784 if(uvedit_uv_selected(scene, efa, tface, 2)) tfa
ce->unwrap |= TF_PIN3; | |
2785 if(efa->v4) | |
2786 if(uvedit_uv_selected(scene, efa, tface,
3)) tface->unwrap |= TF_PIN4; | |
2787 } | |
2788 else { | |
2789 if(uvedit_uv_selected(scene, efa, tface, 0)) tfa
ce->unwrap &= ~TF_PIN1; | |
2790 if(uvedit_uv_selected(scene, efa, tface, 1)) tfa
ce->unwrap &= ~TF_PIN2; | |
2791 if(uvedit_uv_selected(scene, efa, tface, 2)) tfa
ce->unwrap &= ~TF_PIN3; | |
2792 if(efa->v4) | |
2793 if(uvedit_uv_selected(scene, efa, tface,
3)) tface->unwrap &= ~TF_PIN4; | |
2794 } | |
2795 } | |
2796 } | |
2797 ········ | |
2798 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | |
2799 | |
2800 BKE_mesh_end_editmesh(obedit->data, em); | |
2801 return OPERATOR_FINISHED; | |
2802 } | |
2803 | |
2804 static void UV_OT_pin(wmOperatorType *ot) | |
2805 { | |
2806 /* identifiers */ | |
2807 ot->name= "Pin"; | |
2808 ot->description= "Set/clear selected UV vertices as anchored between mul
tiple unwrap operations"; | |
2809 ot->idname= "UV_OT_pin"; | |
2810 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2811 ········ | |
2812 /* api callbacks */ | |
2813 ot->exec= pin_exec; | |
2814 ot->poll= ED_operator_uvedit; | |
2815 | |
2816 /* properties */ | |
2817 RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the se
lection instead of setting it."); | |
2818 } | |
2819 | |
2820 /******************* select pinned operator ***************/ | |
2821 | |
2822 static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) | |
2823 { | |
2824 Scene *scene= CTX_data_scene(C); | |
2825 Object *obedit= CTX_data_edit_object(C); | |
2826 Image *ima= CTX_data_edit_image(C); | |
2827 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2828 EditFace *efa; | |
2829 MTFace *tface; | |
2830 ········ | |
2831 for(efa= em->faces.first; efa; efa= efa->next) { | |
2832 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | |
2833 | |
2834 if(uvedit_face_visible(scene, ima, efa, tface)) { | |
2835 if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa,
tface, 0); | |
2836 if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa,
tface, 1); | |
2837 if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa,
tface, 2); | |
2838 if(efa->v4) { | |
2839 if(tface->unwrap & TF_PIN4) uvedit_uv_select(sce
ne, efa, tface, 3); | |
2840 } | |
2841 } | |
2842 } | |
2843 ········ | |
2844 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2845 | |
2846 BKE_mesh_end_editmesh(obedit->data, em); | |
2847 return OPERATOR_FINISHED; | |
2848 } | |
2849 | |
2850 static void UV_OT_select_pinned(wmOperatorType *ot) | |
2851 { | |
2852 /* identifiers */ | |
2853 ot->name= "Selected Pinned"; | |
2854 ot->description= "Select all pinned UV vertices"; | |
2855 ot->idname= "UV_OT_select_pinned"; | |
2856 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2857 ········ | |
2858 /* api callbacks */ | |
2859 ot->exec= select_pinned_exec; | |
2860 ot->poll= ED_operator_uvedit; | |
2861 } | |
2862 | |
2863 /********************** hide operator *********************/ | |
2864 | |
2865 static int hide_exec(bContext *C, wmOperator *op) | |
2866 { | |
2867 SpaceImage *sima= CTX_wm_space_image(C); | |
2868 ToolSettings *ts= CTX_data_tool_settings(C); | |
2869 Object *obedit= CTX_data_edit_object(C); | |
2870 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
2871 EditFace *efa; | |
2872 MTFace *tf; | |
2873 int swap= RNA_boolean_get(op->ptr, "unselected"); | |
2874 int facemode= sima ? sima->flag & SI_SELACTFACE : 0; | |
2875 | |
2876 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
2877 EM_hide_mesh(em, swap); | |
2878 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2879 | |
2880 BKE_mesh_end_editmesh(obedit->data, em); | |
2881 return OPERATOR_FINISHED; | |
2882 } | |
2883 ········ | |
2884 if(swap) { | |
2885 for(efa= em->faces.first; efa; efa= efa->next) { | |
2886 if(efa->f & SELECT) { | |
2887 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); | |
2888 if(facemode) { | |
2889 /* Pretend face mode */ | |
2890 if(( (efa->v4==NULL &&· | |
2891 ( tf->flag & (TF_S
EL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) )
|| | |
2892 ( tf->flag & (TF_S
EL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)
) == 0) { | |
2893 ················································ | |
2894 if(em->selectmode == SCE_SELECT_
FACE) { | |
2895 efa->f &= ~SELECT; | |
2896 /* must re-select after
*/ | |
2897 efa->e1->f &= ~SELECT; | |
2898 efa->e2->f &= ~SELECT; | |
2899 efa->e3->f &= ~SELECT; | |
2900 if(efa->e4) efa->e4->f &
= ~SELECT; | |
2901 } | |
2902 else | |
2903 EM_select_face(efa, 0); | |
2904 } | |
2905 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
2906 } | |
2907 else if(em->selectmode == SCE_SELECT_FACE) { | |
2908 const char select_flag= efa->v4 ? (TF_SE
L1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
2909 if((tf->flag & select_flag)==0) { | |
2910 EM_select_face(efa, 0); | |
2911 tf->flag &= ~(TF_SEL1|TF_SEL2|TF
_SEL3|TF_SEL4); | |
2912 } | |
2913 } | |
2914 else { | |
2915 /* EM_deselect_flush will deselect the f
ace */ | |
2916 if((tf->flag & TF_SEL1)==0)
efa->v1->f &= ~SELECT; | |
2917 if((tf->flag & TF_SEL2)==0)
efa->v2->f &= ~SELECT; | |
2918 if((tf->flag & TF_SEL3)==0)
efa->v3->f &= ~SELECT; | |
2919 if((efa->v4) && (tf->flag & TF_SEL4)==0)
efa->v4->f &= ~SELECT;·················· | |
2920 | |
2921 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
2922 } | |
2923 } | |
2924 } | |
2925 } | |
2926 else { | |
2927 for(efa= em->faces.first; efa; efa= efa->next) { | |
2928 if(efa->f & SELECT) { | |
2929 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); | |
2930 | |
2931 if(facemode) { | |
2932 if( (efa->v4==NULL &&· | |
2933 ( tf->flag & (TF_S
EL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) )
|| | |
2934 ( tf->flag & (TF_S
EL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)
) { | |
2935 ················································ | |
2936 if(em->selectmode == SCE_SELECT_
FACE) { | |
2937 efa->f &= ~SELECT; | |
2938 /* must re-select after
*/ | |
2939 efa->e1->f &= ~SELECT; | |
2940 efa->e2->f &= ~SELECT; | |
2941 efa->e3->f &= ~SELECT; | |
2942 if(efa->e4) efa->e4->f &
= ~SELECT; | |
2943 } | |
2944 else | |
2945 EM_select_face(efa, 0); | |
2946 } | |
2947 | |
2948 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
2949 } | |
2950 else if(em->selectmode == SCE_SELECT_FACE) { | |
2951 const char select_flag= efa->v4 ? (TF_SE
L1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); | |
2952 if(tf->flag & select_flag) | |
2953 EM_select_face(efa, 0); | |
2954 | |
2955 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
2956 } | |
2957 else { | |
2958 /* EM_deselect_flush will deselect the f
ace */ | |
2959 if(tf->flag & TF_SEL1)
efa->v1->f &= ~SELECT; | |
2960 if(tf->flag & TF_SEL2)
efa->v2->f &= ~SELECT; | |
2961 if(tf->flag & TF_SEL3)
efa->v3->f &= ~SELECT; | |
2962 if((efa->v4) && tf->flag & TF_SEL4)
efa->v4->f &= ~SELECT; | |
2963 | |
2964 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF
_SEL4); | |
2965 } | |
2966 } | |
2967 } | |
2968 } | |
2969 ········ | |
2970 /*deselects too many but ok for now*/ | |
2971 if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) | |
2972 EM_deselect_flush(em); | |
2973 ········ | |
2974 if(em->selectmode==SCE_SELECT_FACE) { | |
2975 /* de-selected all edges from faces that were de-selected. | |
2976 * now make sure all faces that are selected also have selected
edges */ | |
2977 for(efa= em->faces.first; efa; efa= efa->next) | |
2978 if(efa->f & SELECT) | |
2979 EM_select_face(efa, 1); | |
2980 } | |
2981 ········ | |
2982 EM_validate_selections(em); | |
2983 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
2984 | |
2985 BKE_mesh_end_editmesh(obedit->data, em); | |
2986 return OPERATOR_FINISHED; | |
2987 } | |
2988 | |
2989 static void UV_OT_hide(wmOperatorType *ot) | |
2990 { | |
2991 /* identifiers */ | |
2992 ot->name= "Hide Selected"; | |
2993 ot->description= "Hide (un)selected UV vertices"; | |
2994 ot->idname= "UV_OT_hide"; | |
2995 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2996 ········ | |
2997 /* api callbacks */ | |
2998 ot->exec= hide_exec; | |
2999 ot->poll= ED_operator_uvedit; | |
3000 | |
3001 /* props */ | |
3002 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselecte
d rather than selected."); | |
3003 } | |
3004 | |
3005 /****************** reveal operator ******************/ | |
3006 | |
3007 static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) | |
3008 { | |
3009 SpaceImage *sima= CTX_wm_space_image(C); | |
3010 ToolSettings *ts= CTX_data_tool_settings(C); | |
3011 Object *obedit= CTX_data_edit_object(C); | |
3012 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); | |
3013 EditFace *efa; | |
3014 MTFace *tf; | |
3015 int facemode= sima ? sima->flag & SI_SELACTFACE : 0; | |
3016 int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; | |
3017 ········ | |
3018 /* call the mesh function if we are in mesh sync sel */ | |
3019 if(ts->uv_flag & UV_SYNC_SELECTION) { | |
3020 EM_reveal_mesh(em); | |
3021 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
3022 | |
3023 BKE_mesh_end_editmesh(obedit->data, em); | |
3024 return OPERATOR_FINISHED; | |
3025 } | |
3026 ········ | |
3027 if(facemode) { | |
3028 if(em->selectmode == SCE_SELECT_FACE) { | |
3029 for(efa= em->faces.first; efa; efa= efa->next) { | |
3030 if(!(efa->h) && !(efa->f & SELECT)) { | |
3031 tf= CustomData_em_get(&em->fdata, efa->d
ata, CD_MTFACE); | |
3032 EM_select_face(efa, 1); | |
3033 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_S
EL4; | |
3034 } | |
3035 } | |
3036 } | |
3037 else { | |
3038 /* enable adjacent faces to have disconnected UV selecti
ons if sticky is disabled */ | |
3039 if(!stickymode) { | |
3040 for(efa= em->faces.first; efa; efa= efa->next) { | |
3041 if(!(efa->h) && !(efa->f & SELECT)) { | |
3042 /* All verts must be unselected
for the face to be selected in the UV view */ | |
3043 if((efa->v1->f&SELECT)==0 && (ef
a->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==NULL || (efa->v4->f&S
ELECT)==0)) { | |
3044 tf= CustomData_em_get(&e
m->fdata, efa->data, CD_MTFACE); | |
3045 | |
3046 tf->flag |= TF_SEL1|TF_S
EL2|TF_SEL3|TF_SEL4; | |
3047 /* Cant use EM_select_fa
ce here because it unselects the verts | |
3048 * and we cant tell if t
he face was totally unselected or not */ | |
3049 /*EM_select_face(efa, 1)
; | |
3050 *· | |
3051 * See Loop with EM_sele
ct_face() below... */ | |
3052 efa->f |= SELECT; | |
3053 } | |
3054 } | |
3055 } | |
3056 } | |
3057 else { | |
3058 for(efa= em->faces.first; efa; efa= efa->next) { | |
3059 if(!(efa->h) && !(efa->f & SELECT)) { | |
3060 tf= CustomData_em_get(&em->fdata
, efa->data, CD_MTFACE); | |
3061 | |
3062 if((efa->v1->f & SELECT)==0)
{tf->flag |= TF_SEL1;} | |
3063 if((efa->v2->f & SELECT)==0)
{tf->flag |= TF_SEL2;} | |
3064 if((efa->v3->f & SELECT)==0)
{tf->flag |= TF_SEL3;} | |
3065 if((efa->v4 && (efa->v4->f & SEL
ECT)==0)) {tf->flag |= TF_SEL4;} | |
3066 | |
3067 efa->f |= SELECT; | |
3068 } | |
3069 } | |
3070 } | |
3071 ························ | |
3072 /* Select all edges and verts now */ | |
3073 for(efa= em->faces.first; efa; efa= efa->next) | |
3074 /* we only selected the face flags, and didnt ch
anges edges or verts, fix this now */ | |
3075 if(!(efa->h) && (efa->f & SELECT)) | |
3076 EM_select_face(efa, 1); | |
3077 | |
3078 EM_select_flush(em); | |
3079 } | |
3080 } | |
3081 else if(em->selectmode == SCE_SELECT_FACE) { | |
3082 for(efa= em->faces.first; efa; efa= efa->next) { | |
3083 if(!(efa->h) && !(efa->f & SELECT)) { | |
3084 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); | |
3085 efa->f |= SELECT; | |
3086 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; | |
3087 } | |
3088 } | |
3089 ················ | |
3090 /* Select all edges and verts now */ | |
3091 for(efa= em->faces.first; efa; efa= efa->next) | |
3092 /* we only selected the face flags, and didnt changes ed
ges or verts, fix this now */ | |
3093 if(!(efa->h) && (efa->f & SELECT)) | |
3094 EM_select_face(efa, 1); | |
3095 } | |
3096 else { | |
3097 for(efa= em->faces.first; efa; efa= efa->next) { | |
3098 if(!(efa->h) && !(efa->f & SELECT)) { | |
3099 tf= CustomData_em_get(&em->fdata, efa->data, CD_
MTFACE); | |
3100 | |
3101 if((efa->v1->f & SELECT)==0)
{tf->flag |= TF_SEL1;} | |
3102 if((efa->v2->f & SELECT)==0)
{tf->flag |= TF_SEL2;} | |
3103 if((efa->v3->f & SELECT)==0)
{tf->flag |= TF_SEL3;} | |
3104 if((efa->v4 && (efa->v4->f & SELECT)==0))
{tf->flag |= TF_SEL4;} | |
3105 | |
3106 efa->f |= SELECT; | |
3107 } | |
3108 } | |
3109 ················ | |
3110 /* Select all edges and verts now */ | |
3111 for(efa= em->faces.first; efa; efa= efa->next) | |
3112 /* we only selected the face flags, and didnt changes ed
ges or verts, fix this now */ | |
3113 if(!(efa->h) && (efa->f & SELECT)) | |
3114 EM_select_face(efa, 1); | |
3115 } | |
3116 | |
3117 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); | |
3118 | |
3119 BKE_mesh_end_editmesh(obedit->data, em); | |
3120 return OPERATOR_FINISHED; | |
3121 } | |
3122 | |
3123 static void UV_OT_reveal(wmOperatorType *ot) | |
3124 { | |
3125 /* identifiers */ | |
3126 ot->name= "Reveal Hidden"; | |
3127 ot->description= "Reveal all hidden UV vertices"; | |
3128 ot->idname= "UV_OT_reveal"; | |
3129 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
3130 ········ | |
3131 /* api callbacks */ | |
3132 ot->exec= reveal_exec; | |
3133 ot->poll= ED_operator_uvedit; | |
3134 } | |
3135 | |
3136 /******************** set 3d cursor operator ********************/ | |
3137 | |
3138 static int set_2d_cursor_exec(bContext *C, wmOperator *op) | |
3139 { | |
3140 SpaceImage *sima = CTX_wm_space_image(C); | |
3141 float location[2]; | |
3142 | |
3143 if(!sima) | |
3144 return OPERATOR_CANCELLED; | |
3145 | |
3146 RNA_float_get_array(op->ptr, "location", location); | |
3147 sima->cursor[0]= location[0]; | |
3148 sima->cursor[1]= location[1]; | |
3149 ········ | |
3150 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, NULL); | |
3151 ········ | |
3152 return OPERATOR_FINISHED; | |
3153 } | |
3154 | |
3155 static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
3156 { | |
3157 ARegion *ar= CTX_wm_region(C); | |
3158 float location[2]; | |
3159 | |
3160 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &loca
tion[0], &location[1]); | |
3161 RNA_float_set_array(op->ptr, "location", location); | |
3162 | |
3163 return set_2d_cursor_exec(C, op); | |
3164 } | |
3165 | |
3166 static void UV_OT_cursor_set(wmOperatorType *ot) | |
3167 { | |
3168 /* identifiers */ | |
3169 ot->name= "Set 2D Cursor"; | |
3170 ot->description= "Set 2D cursor location"; | |
3171 ot->idname= "UV_OT_cursor_set"; | |
3172 ········ | |
3173 /* api callbacks */ | |
3174 ot->exec= set_2d_cursor_exec; | |
3175 ot->invoke= set_2d_cursor_invoke; | |
3176 ot->poll= ED_operator_image_active; /* requires space image */; | |
3177 | |
3178 /* flags */ | |
3179 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
3180 | |
3181 /* properties */ | |
3182 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "
Location", "Cursor location in 0.0-1.0 coordinates.", -10.0f, 10.0f); | |
3183 } | |
3184 | |
3185 /********************** set tile operator **********************/ | |
3186 | |
3187 static int set_tile_exec(bContext *C, wmOperator *op) | |
3188 { | |
3189 Image *ima= CTX_data_edit_image(C); | |
3190 int tile[2]; | |
3191 Object *obedit= CTX_data_edit_object(C); | |
3192 | |
3193 RNA_int_get_array(op->ptr, "tile", tile); | |
3194 | |
3195 if(uvedit_set_tile(obedit, ima, tile[0] + ima->xrep*tile[1])) { | |
3196 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | |
3197 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, NULL); | |
3198 | |
3199 return OPERATOR_FINISHED; | |
3200 } | |
3201 ········ | |
3202 return OPERATOR_CANCELLED; | |
3203 } | |
3204 | |
3205 static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
3206 { | |
3207 SpaceImage *sima= CTX_wm_space_image(C); | |
3208 Image *ima= CTX_data_edit_image(C); | |
3209 ARegion *ar= CTX_wm_region(C); | |
3210 float fx, fy; | |
3211 int tile[2]; | |
3212 | |
3213 if(!ima || !(ima->tpageflag & IMA_TILES)) | |
3214 return OPERATOR_CANCELLED; | |
3215 | |
3216 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx,
&fy); | |
3217 | |
3218 if(fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) { | |
3219 fx= fx*ima->xrep; | |
3220 fy= fy*ima->yrep; | |
3221 ················ | |
3222 tile[0]= fx; | |
3223 tile[1]= fy; | |
3224 ················ | |
3225 sima->curtile= tile[1]*ima->xrep + tile[0]; | |
3226 RNA_int_set_array(op->ptr, "tile", tile); | |
3227 } | |
3228 | |
3229 return set_tile_exec(C, op); | |
3230 } | |
3231 | |
3232 static void UV_OT_tile_set(wmOperatorType *ot) | |
3233 { | |
3234 /* identifiers */ | |
3235 ot->name= "Set Tile"; | |
3236 ot->description= "Set UV image tile coordinates"; | |
3237 ot->idname= "UV_OT_tile_set"; | |
3238 ········ | |
3239 /* api callbacks */ | |
3240 ot->exec= set_tile_exec; | |
3241 ot->invoke= set_tile_invoke; | |
3242 ot->poll= ED_operator_image_active; /* requires space image */; | |
3243 | |
3244 /* flags */ | |
3245 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
3246 | |
3247 /* properties */ | |
3248 RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile
coordinate.", 0, 10); | |
3249 } | |
3250 | |
3251 /* ************************** registration **********************************/ | |
3252 | |
3253 void ED_operatortypes_uvedit(void) | |
3254 { | |
3255 WM_operatortype_append(UV_OT_select_all); | |
3256 WM_operatortype_append(UV_OT_select); | |
3257 WM_operatortype_append(UV_OT_select_loop); | |
3258 WM_operatortype_append(UV_OT_select_linked); | |
3259 WM_operatortype_append(UV_OT_select_linked_pick); | |
3260 WM_operatortype_append(UV_OT_unlink_selected); | |
3261 WM_operatortype_append(UV_OT_select_pinned); | |
3262 WM_operatortype_append(UV_OT_select_border); | |
3263 WM_operatortype_append(UV_OT_circle_select); | |
3264 | |
3265 WM_operatortype_append(UV_OT_snap_cursor); | |
3266 WM_operatortype_append(UV_OT_snap_selected); | |
3267 | |
3268 WM_operatortype_append(UV_OT_align); | |
3269 WM_operatortype_append(UV_OT_stitch); | |
3270 WM_operatortype_append(UV_OT_weld); | |
3271 WM_operatortype_append(UV_OT_pin); | |
3272 | |
3273 WM_operatortype_append(UV_OT_average_islands_scale); | |
3274 WM_operatortype_append(UV_OT_cube_project); | |
3275 WM_operatortype_append(UV_OT_cylinder_project); | |
3276 WM_operatortype_append(UV_OT_from_view); | |
3277 WM_operatortype_append(UV_OT_minimize_stretch); | |
3278 WM_operatortype_append(UV_OT_pack_islands); | |
3279 WM_operatortype_append(UV_OT_reset); | |
3280 WM_operatortype_append(UV_OT_sphere_project); | |
3281 WM_operatortype_append(UV_OT_unwrap); | |
3282 | |
3283 WM_operatortype_append(UV_OT_reveal); | |
3284 WM_operatortype_append(UV_OT_hide); | |
3285 | |
3286 WM_operatortype_append(UV_OT_cursor_set); | |
3287 WM_operatortype_append(UV_OT_tile_set); | |
3288 } | |
3289 | |
3290 void ED_keymap_uvedit(wmKeyConfig *keyconf) | |
3291 { | |
3292 wmKeyMap *keymap; | |
3293 wmKeyMapItem *kmi; | |
3294 ········ | |
3295 keymap= WM_keymap_find(keyconf, "UV Editor", 0, 0); | |
3296 keymap->poll= ED_operator_uvedit; | |
3297 ········ | |
3298 /* pick selection */ | |
3299 WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); | |
3300 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE,
KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); | |
3301 WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMOUSE, KM_PRESS, K
M_ALT, 0); | |
3302 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMO
USE, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "extend", 1); | |
3303 | |
3304 /* border/circle selection */ | |
3305 WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY, KM_PRESS, 0, 0); | |
3306 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY,
KM_PRESS, KM_SHIFT, 0)->ptr, "pinned", 1); | |
3307 WM_keymap_add_item(keymap, "UV_OT_circle_select", CKEY, KM_PRESS, 0, 0); | |
3308 | |
3309 /* selection manipulation */ | |
3310 WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY, KM_PRESS, KM_CTR
L, 0); | |
3311 WM_keymap_add_item(keymap, "UV_OT_select_linked_pick", LKEY, KM_PRESS, 0
, 0); | |
3312 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY,
KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "extend", TRUE); | |
3313 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_linked_pick", L
KEY, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", TRUE); | |
3314 | |
3315 WM_keymap_add_item(keymap, "UV_OT_unlink_selected", LKEY, KM_PRESS, KM_A
LT, 0); | |
3316 WM_keymap_add_item(keymap, "UV_OT_select_all", AKEY, KM_PRESS, 0, 0); | |
3317 RNA_enum_set(WM_keymap_add_item(keymap, "UV_OT_select_all", IKEY, KM_PRE
SS, KM_CTRL, 0)->ptr, "action", SEL_INVERT); | |
3318 WM_keymap_add_item(keymap, "UV_OT_select_pinned", PKEY, KM_PRESS, KM_SHI
FT, 0); | |
3319 | |
3320 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_weldalign", WKEY, KM_PRESS, 0,
0); | |
3321 | |
3322 /* uv operations */ | |
3323 WM_keymap_add_item(keymap, "UV_OT_stitch", VKEY, KM_PRESS, 0, 0); | |
3324 WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, 0, 0); | |
3325 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS,
KM_ALT, 0)->ptr, "clear", 1); | |
3326 | |
3327 /* unwrap */ | |
3328 WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0); | |
3329 WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_
CTRL, 0); | |
3330 WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL
, 0); | |
3331 WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS
, KM_CTRL, 0); | |
3332 | |
3333 /* hide */ | |
3334 WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, 0, 0); | |
3335 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS,
KM_SHIFT, 0)->ptr, "unselected", 1); | |
3336 WM_keymap_add_item(keymap, "UV_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0); | |
3337 | |
3338 /* cursor */ | |
3339 WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0,
0); | |
3340 WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_S
HIFT, 0); | |
3341 ········ | |
3342 /* menus */ | |
3343 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT
, 0); | |
3344 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_select_mode", TABKEY, KM_PRESS,
KM_CTRL, 0); | |
3345 | |
3346 /* pivot */ | |
3347 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_
PRESS, 0, 0); | |
3348 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"
); | |
3349 RNA_string_set(kmi->ptr, "value", "CENTER"); | |
3350 | |
3351 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_
PRESS, KM_CTRL, 0); | |
3352 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"
); | |
3353 RNA_string_set(kmi->ptr, "value", "MEDIAN"); | |
3354 | |
3355 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM
_PRESS, 0, 0); | |
3356 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"
); | |
3357 RNA_string_set(kmi->ptr, "value", "CURSOR"); | |
3358 | |
3359 ED_object_generic_keymap(keyconf, keymap, 2); | |
3360 | |
3361 transform_keymap_for_space(keyconf, keymap, SPACE_IMAGE); | |
3362 } | |
3363 | |
LEFT | RIGHT |