LEFT | RIGHT |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * 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, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 } UvAdjacencyElement; | 79 } UvAdjacencyElement; |
80 | 80 |
81 typedef struct UvEdge { | 81 typedef struct UvEdge { |
82 unsigned int uv1; | 82 unsigned int uv1; |
83 unsigned int uv2; | 83 unsigned int uv2; |
84 /* general use flag (Used to check if edge is boundary here, and propaga
tes to adjacency elements) */ | 84 /* general use flag (Used to check if edge is boundary here, and propaga
tes to adjacency elements) */ |
85 char flag; | 85 char flag; |
86 }UvEdge; | 86 }UvEdge; |
87 | 87 |
88 | 88 |
89 typedef struct UVInitialStrokeElement{ | |
90 /* index to unique uv */ | |
91 int uv; | |
92 /* strength of brush on initial position */ | |
93 float strength; | |
94 /* initial uv position */ | |
95 float initial_uv[2]; | |
96 }UVInitialStrokeElement; | |
97 | |
98 typedef struct UVInitialStroke{ | |
99 /* Initial Selection,for grab brushes for instance */ | |
100 UVInitialStrokeElement *initialSelection; | |
101 | |
102 /* total initially selected UVs*/ | |
103 int totalInitialSelected; | |
104 | |
105 /* initial mouse coordinates */ | |
106 float init_coord[2]; | |
107 }UVInitialStroke; | |
108 | |
109 | |
110 /* custom data for uv smoothing brush */ | 89 /* custom data for uv smoothing brush */ |
111 typedef struct UvSculptData{ | 90 typedef struct UvSculptData{ |
112 /* Contains the first of each set of coincident uvs. | 91 /* Contains the first of each set of coincident uvs. |
113 * These will be used to perform smoothing on and propagate the changes | 92 * These will be used to perform smoothing on and propagate the changes |
114 * to their coincident uvs */ | 93 * to their coincident uvs */ |
115 UvAdjacencyElement *uv; | 94 UvAdjacencyElement *uv; |
116 | 95 |
117 /* ...Is what it says */ | 96 /* ...Is what it says */ |
118 int totalUniqueUvs; | 97 int totalUniqueUvs; |
119 | 98 |
120 /* Edges used for adjacency info, used with laplacian smoothing */ | 99 /* Edges used for adjacency info, used with laplacian smoothing */ |
121 UvEdge *uvedges; | 100 UvEdge *uvedges; |
122 | 101 |
123 /* Need I say more? */ | 102 /* Need I say more? */ |
124 int totalUvEdges; | 103 int totalUvEdges; |
125 | |
126 /* data for initial stroke, used by tools like grab */ | |
127 UVInitialStroke *initial_stroke; | |
128 | 104 |
129 /* Timer to be used for airbrush-type brush */ | 105 /* Timer to be used for airbrush-type brush */ |
130 wmTimer *timer; | 106 wmTimer *timer; |
131 | 107 |
132 /* To determine quickly adjacent uvs */ | 108 /* To determine quickly adjacent uvs */ |
133 UvElementMap *elementMap; | 109 UvElementMap *elementMap; |
134 | 110 |
135 /* uvsmooth Paint for fast reference */ | 111 /* uvsmooth Paint for fast reference */ |
136 Paint *uvsculpt; | 112 Paint *uvsculpt; |
137 }UvSculptData; | 113 }UvSculptData; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 */ | 323 */ |
348 else if(tool == UV_SCULPT_TOOL_RELAX){ | 324 else if(tool == UV_SCULPT_TOOL_RELAX){ |
349 unsigned int method = CTX_data_scene(C)->toolsettings->uv_relax_
method; | 325 unsigned int method = CTX_data_scene(C)->toolsettings->uv_relax_
method; |
350 if(method == UV_SCULPT_TOOL_RELAX_HC){ | 326 if(method == UV_SCULPT_TOOL_RELAX_HC){ |
351 HC_relaxation_iteration_uv(em, sculptdata, co, alpha, ra
dius, aspectRatio); | 327 HC_relaxation_iteration_uv(em, sculptdata, co, alpha, ra
dius, aspectRatio); |
352 }else{ | 328 }else{ |
353 laplacian_relaxation_iteration_uv(em, sculptdata, co, al
pha, radius, aspectRatio); | 329 laplacian_relaxation_iteration_uv(em, sculptdata, co, al
pha, radius, aspectRatio); |
354 } | 330 } |
355 } | 331 } |
356 | 332 |
357 /* | |
358 * Grab Tool | |
359 */ | |
360 else if(tool == UV_SCULPT_TOOL_GRAB){ | |
361 int i; | |
362 float diff[2]; | |
363 sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord); | |
364 | |
365 for(i = 0; i < sculptdata->initial_stroke->totalInitialSelected;
i++ ){ | |
366 UvElement *element; | |
367 int uvindex = sculptdata->initial_stroke->initialSelecti
on[i].uv; | |
368 float strength = sculptdata->initial_stroke->initialSele
ction[i].strength; | |
369 sculptdata->uv[uvindex].uv[0] = sculptdata->initial_stro
ke->initialSelection[i].initial_uv[0] + strength*diff[0]; | |
370 sculptdata->uv[uvindex].uv[1] = sculptdata->initial_stro
ke->initialSelection[i].initial_uv[1] + strength*diff[1]; | |
371 | |
372 for(element = sculptdata->uv[uvindex].element; element;
element = element->next){ | |
373 MTFace *mt; | |
374 if(element->separate && element != sculptdata->u
v[uvindex].element) | |
375 break; | |
376 mt = CustomData_em_get(&em->fdata, element->face
->data, CD_MTFACE); | |
377 copy_v2_v2(mt->uv[element->tfindex], sculptdata-
>uv[uvindex].uv); | |
378 } | |
379 } | |
380 } | |
381 | |
382 BKE_mesh_end_editmesh(obedit->data, em); | 333 BKE_mesh_end_editmesh(obedit->data, em); |
383 } | 334 } |
384 | 335 |
385 | 336 |
386 static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op) | 337 static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op) |
387 { | 338 { |
388 UvSculptData *data = op->customdata; | 339 UvSculptData *data = op->customdata; |
389 if(data->timer){ | 340 if(data->timer){ |
390 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data-
>timer); | 341 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data-
>timer); |
391 } | 342 } |
392 if(data->elementMap) | 343 if(data->elementMap) |
393 { | 344 { |
394 EM_free_uv_element_map(data->elementMap); | 345 EM_free_uv_element_map(data->elementMap); |
395 } | 346 } |
396 if(data->uv){ | 347 if(data->uv){ |
397 MEM_freeN(data->uv); | 348 MEM_freeN(data->uv); |
398 } | 349 } |
399 if(data->uvedges){ | 350 if(data->uvedges){ |
400 MEM_freeN(data->uvedges); | 351 MEM_freeN(data->uvedges); |
401 } | 352 } |
402 » if(data->initial_stroke){ | 353 |
403 » » if(data->initial_stroke->initialSelection){ | |
404 » » » MEM_freeN(data->initial_stroke->initialSelection); | |
405 » » } | |
406 » » MEM_freeN(data->initial_stroke); | |
407 » } | |
408 MEM_freeN(data); | 354 MEM_freeN(data); |
409 op->customdata = NULL; | 355 op->customdata = NULL; |
410 } | 356 } |
411 | 357 |
412 static int get_uv_element_offset_from_face(UvElementMap *map, EditFace *efa, int
index, int island_index, int doIslands){ | 358 static int get_uv_element_offset_from_face(UvElementMap *map, EditFace *efa, int
index, int island_index, int doIslands){ |
413 » UvElement *element = get_uv_element(map, efa, index); | 359 » UvElement *element = ED_get_uv_element(map, efa, index); |
414 if(!element || (doIslands && element->island != island_index)){ | 360 if(!element || (doIslands && element->island != island_index)){ |
415 return -1; | 361 return -1; |
416 } | 362 } |
417 return element - map->buf; | 363 return element - map->buf; |
418 } | 364 } |
419 | 365 |
420 | 366 |
421 static unsigned int uv_edge_hash(const void *key){ | 367 static unsigned int uv_edge_hash(const void *key){ |
422 UvEdge *edge = (UvEdge *)key; | 368 UvEdge *edge = (UvEdge *)key; |
423 return· | 369 return· |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 } | 429 } |
484 | 430 |
485 /* Mouse coordinates, useful for some functions like grab and sc
ulpt all islands */ | 431 /* Mouse coordinates, useful for some functions like grab and sc
ulpt all islands */ |
486 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1
], &co[0], &co[1]); | 432 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1
], &co[0], &co[1]); |
487 | 433 |
488 /* we need to find the active island here */ | 434 /* we need to find the active island here */ |
489 if(do_island_optimization){ | 435 if(do_island_optimization){ |
490 UvElement *element; | 436 UvElement *element; |
491 NearestHit hit; | 437 NearestHit hit; |
492 Image *ima= CTX_data_edit_image(C); | 438 Image *ima= CTX_data_edit_image(C); |
493 » » » find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); | 439 » » » ED_find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); |
494 | 440 |
495 » » » element = get_uv_element(data->elementMap, hit.efa, hit.
uv); | 441 » » » element = ED_get_uv_element(data->elementMap, hit.efa, h
it.uv); |
496 island_index = element->island; | 442 island_index = element->island; |
497 } | 443 } |
498 | 444 |
499 | 445 |
500 /* Count 'unique' uvs */ | 446 /* Count 'unique' uvs */ |
501 for(i = 0; i < data->elementMap->totalUVs; i++){ | 447 for(i = 0; i < data->elementMap->totalUVs; i++){ |
502 if(data->elementMap->buf[i].separate | 448 if(data->elementMap->buf[i].separate |
503 && (!do_island_optimization || data->elementMap->buf[i].
island == island_index)){ | 449 && (!do_island_optimization || data->elementMap->buf[i].
island == island_index)){ |
504 counter++; | 450 counter++; |
505 } | 451 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 | 565 |
620 /* transfer boundary edge property to uvs */ | 566 /* transfer boundary edge property to uvs */ |
621 if(ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS){ | 567 if(ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS){ |
622 for(i = 0; i < data->totalUvEdges; i++){ | 568 for(i = 0; i < data->totalUvEdges; i++){ |
623 if(!data->uvedges[i].flag){ | 569 if(!data->uvedges[i].flag){ |
624 data->uv[data->uvedges[i].uv1].flag |= M
ARK_BOUNDARY; | 570 data->uv[data->uvedges[i].uv1].flag |= M
ARK_BOUNDARY; |
625 data->uv[data->uvedges[i].uv2].flag |= M
ARK_BOUNDARY; | 571 data->uv[data->uvedges[i].uv2].flag |= M
ARK_BOUNDARY; |
626 } | 572 } |
627 } | 573 } |
628 } | 574 } |
629 | |
630 /* Allocate initial selection for grab tool */ | |
631 if(ts->uv_sculpt_tool == UV_SCULPT_TOOL_GRAB){ | |
632 float radius, radius_root; | |
633 unsigned int tool; | |
634 UvSculptData *sculptdata = (UvSculptData *)op->customdat
a; | |
635 SpaceImage *sima; | |
636 int width, height; | |
637 float aspectRatio; | |
638 float alpha, zoomx, zoomy; | |
639 Brush *brush = paint_brush(sculptdata->uvsculpt); | |
640 tool = CTX_data_scene(C)->toolsettings->uv_sculpt_tool; | |
641 | |
642 alpha = brush_alpha(brush); | |
643 | |
644 radius = brush_size(brush); | |
645 sima = CTX_wm_space_image(C); | |
646 ED_space_image_size(sima, &width, &height); | |
647 ED_space_image_zoom(sima, ar, &zoomx, &zoomy); | |
648 | |
649 aspectRatio = width/(float)height; | |
650 radius /= (width*zoomx); | |
651 radius = radius*radius; | |
652 radius_root = sqrt(radius); | |
653 | |
654 /* Allocate selection stack */ | |
655 data->initial_stroke = MEM_mallocN(sizeof(*data->initial
_stroke), "uv_sculpt_initial_stroke"); | |
656 if(!data->initial_stroke){ | |
657 uv_sculpt_stroke_exit(C, op); | |
658 } | |
659 data->initial_stroke->initialSelection = MEM_mallocN(si
zeof(*data->initial_stroke->initialSelection)*data->totalUniqueUvs, "uv_sculpt_i
nitial_selection"); | |
660 if(!data->initial_stroke->initialSelection){ | |
661 uv_sculpt_stroke_exit(C, op); | |
662 } | |
663 | |
664 copy_v2_v2(data->initial_stroke->init_coord, co); | |
665 | |
666 counter = 0; | |
667 | |
668 for (i = 0; i < data->totalUniqueUvs; i++){ | |
669 float dist, diff[2]; | |
670 if(data->uv[i].flag & MARK_BOUNDARY){ | |
671 continue; | |
672 } | |
673 | |
674 sub_v2_v2v2(diff, data->uv[i].uv, co); | |
675 diff[1] /= aspectRatio; | |
676 if((dist = dot_v2v2(diff, diff)) <= radius){ | |
677 float strength; | |
678 strength = alpha*brush_curve_strength(br
ush, sqrt(dist), radius_root); | |
679 | |
680 data->initial_stroke->initialSelection[c
ounter].uv = i; | |
681 data->initial_stroke->initialSelection[c
ounter].strength = strength; | |
682 copy_v2_v2(data->initial_stroke->initial
Selection[counter].initial_uv, data->uv[i].uv); | |
683 counter++; | |
684 } | |
685 } | |
686 | |
687 data->initial_stroke->totalInitialSelected = counter; | |
688 } | |
689 } | 575 } |
690 | 576 |
691 return op->customdata; | 577 return op->customdata; |
692 } | 578 } |
693 | 579 |
694 static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) | 580 static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) |
695 { | 581 { |
696 UvSculptData *data; | 582 UvSculptData *data; |
697 Object *obedit = CTX_data_edit_object(C); | 583 Object *obedit = CTX_data_edit_object(C); |
698 | 584 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 case LEFTMOUSE: | 627 case LEFTMOUSE: |
742 case MIDDLEMOUSE: | 628 case MIDDLEMOUSE: |
743 case RIGHTMOUSE: // XXX hardcoded | 629 case RIGHTMOUSE: // XXX hardcoded |
744 uv_sculpt_stroke_exit(C, op); | 630 uv_sculpt_stroke_exit(C, op); |
745 return OPERATOR_FINISHED; | 631 return OPERATOR_FINISHED; |
746 case MOUSEMOVE: | 632 case MOUSEMOVE: |
747 case INBETWEEN_MOUSEMOVE: | 633 case INBETWEEN_MOUSEMOVE: |
748 uv_sculpt_stroke_apply(C, op, event, obedit); | 634 uv_sculpt_stroke_apply(C, op, event, obedit); |
749 break; | 635 break; |
750 case TIMER: | 636 case TIMER: |
751 » » » if(event->customdata == data->timer && tool != UV_SCULPT
_TOOL_GRAB) | 637 » » » if(event->customdata == data->timer) |
752 uv_sculpt_stroke_apply(C, op, event, obedit); | 638 uv_sculpt_stroke_apply(C, op, event, obedit); |
753 break; | 639 break; |
754 default: | 640 default: |
755 return OPERATOR_RUNNING_MODAL; | 641 return OPERATOR_RUNNING_MODAL; |
756 } | 642 } |
757 | 643 |
758 ED_region_tag_redraw(CTX_wm_region(C)); | 644 ED_region_tag_redraw(CTX_wm_region(C)); |
759 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); | 645 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); |
760 DAG_id_tag_update(obedit->data, 0); | 646 DAG_id_tag_update(obedit->data, 0); |
761 return OPERATOR_RUNNING_MODAL; | 647 return OPERATOR_RUNNING_MODAL; |
(...skipping 11 matching lines...) Expand all Loading... |
773 // ot->exec = uv_sculpt_stroke_exec; | 659 // ot->exec = uv_sculpt_stroke_exec; |
774 ot->modal = uv_sculpt_stroke_modal; | 660 ot->modal = uv_sculpt_stroke_modal; |
775 ot->poll = uv_sculpt_poll; | 661 ot->poll = uv_sculpt_poll; |
776 | 662 |
777 /* flags */ | 663 /* flags */ |
778 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; | 664 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; |
779 | 665 |
780 /* props */ | 666 /* props */ |
781 RNA_def_boolean(ot->srna, "invert", 0, "Invert", "Inverts the operator")
; | 667 RNA_def_boolean(ot->srna, "invert", 0, "Invert", "Inverts the operator")
; |
782 } | 668 } |
LEFT | RIGHT |