Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / uvedit / uvedit_buttons.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup eduv
22  */
23
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_meshdata_types.h"
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_screen_types.h"
33 #include "DNA_space_types.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #include "BLT_translation.h"
40
41 #include "BKE_context.h"
42 #include "BKE_customdata.h"
43 #include "BKE_screen.h"
44 #include "BKE_editmesh.h"
45
46 #include "DEG_depsgraph.h"
47
48 #include "ED_image.h"
49 #include "ED_uvedit.h"
50
51 #include "UI_interface.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #define B_UVEDIT_VERTEX 3
57
58 /* UV Utilities */
59
60 static int uvedit_center(Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float center[2])
61 {
62   BMFace *f;
63   BMLoop *l;
64   BMIter iter, liter;
65   MLoopUV *luv;
66   int tot = 0;
67
68   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
69
70   zero_v2(center);
71   BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
72     if (!uvedit_face_visible_test(scene, obedit, ima, f)) {
73       continue;
74     }
75
76     BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
77       if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
78         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
79         add_v2_v2(center, luv->uv);
80         tot++;
81       }
82     }
83   }
84
85   if (tot > 0) {
86     center[0] /= tot;
87     center[1] /= tot;
88   }
89
90   return tot;
91 }
92
93 static void uvedit_translate(
94     Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float delta[2])
95 {
96   BMFace *f;
97   BMLoop *l;
98   BMIter iter, liter;
99   MLoopUV *luv;
100
101   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
102
103   BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
104     if (!uvedit_face_visible_test(scene, obedit, ima, f)) {
105       continue;
106     }
107
108     BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
109       if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
110         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
111         add_v2_v2(luv->uv, delta);
112       }
113     }
114   }
115 }
116
117 /* Button Functions, using an evil static variable */
118
119 static float uvedit_old_center[2];
120
121 static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
122 {
123   SpaceImage *sima = CTX_wm_space_image(C);
124   Scene *scene = CTX_data_scene(C);
125   Object *obedit = CTX_data_edit_object(C);
126   Image *ima = sima->image;
127   BMEditMesh *em;
128   float center[2];
129   int imx, imy, step, digits;
130   float width = 8 * UI_UNIT_X;
131
132   ED_space_image_get_size(sima, &imx, &imy);
133
134   em = BKE_editmesh_from_object(obedit);
135
136   if (uvedit_center(scene, obedit, em, ima, center)) {
137     float range_xy[2][2] = {
138         {-10.0f, 10.0f},
139         {-10.0f, 10.0f},
140     };
141
142     copy_v2_v2(uvedit_old_center, center);
143
144     /* expand UI range by center */
145     CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
146     CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
147     CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
148     CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
149
150     if (!(sima->flag & SI_COORDFLOATS)) {
151       uvedit_old_center[0] *= imx;
152       uvedit_old_center[1] *= imy;
153
154       mul_v2_fl(range_xy[0], imx);
155       mul_v2_fl(range_xy[1], imy);
156     }
157
158     if (sima->flag & SI_COORDFLOATS) {
159       step = 1;
160       digits = 3;
161     }
162     else {
163       step = 100;
164       digits = 2;
165     }
166
167     UI_block_align_begin(block);
168     uiDefButF(block,
169               UI_BTYPE_NUM,
170               B_UVEDIT_VERTEX,
171               IFACE_("X:"),
172               0,
173               0,
174               width,
175               UI_UNIT_Y,
176               &uvedit_old_center[0],
177               UNPACK2(range_xy[0]),
178               step,
179               digits,
180               "");
181     uiDefButF(block,
182               UI_BTYPE_NUM,
183               B_UVEDIT_VERTEX,
184               IFACE_("Y:"),
185               width,
186               0,
187               width,
188               UI_UNIT_Y,
189               &uvedit_old_center[1],
190               UNPACK2(range_xy[1]),
191               step,
192               digits,
193               "");
194     UI_block_align_end(block);
195   }
196 }
197
198 static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
199 {
200   SpaceImage *sima = CTX_wm_space_image(C);
201   Scene *scene = CTX_data_scene(C);
202   Object *obedit = CTX_data_edit_object(C);
203   Image *ima = sima->image;
204   BMEditMesh *em;
205   float center[2], delta[2];
206   int imx, imy;
207
208   if (event != B_UVEDIT_VERTEX) {
209     return;
210   }
211
212   em = BKE_editmesh_from_object(obedit);
213
214   ED_space_image_get_size(sima, &imx, &imy);
215   uvedit_center(scene, obedit, em, ima, center);
216
217   if (sima->flag & SI_COORDFLOATS) {
218     delta[0] = uvedit_old_center[0] - center[0];
219     delta[1] = uvedit_old_center[1] - center[1];
220   }
221   else {
222     delta[0] = uvedit_old_center[0] / imx - center[0];
223     delta[1] = uvedit_old_center[1] / imy - center[1];
224   }
225
226   uvedit_translate(scene, obedit, em, ima, delta);
227
228   WM_event_add_notifier(C, NC_IMAGE, sima->image);
229   DEG_id_tag_update((ID *)obedit->data, ID_RECALC_GEOMETRY);
230 }
231
232 /* Panels */
233
234 static bool image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
235 {
236   SpaceImage *sima = CTX_wm_space_image(C);
237   if (sima->mode != SI_MODE_UV) {
238     return false;
239   }
240   Object *obedit = CTX_data_edit_object(C);
241   return ED_uvedit_test(obedit);
242 }
243
244 static void image_panel_uv(const bContext *C, Panel *pa)
245 {
246   uiBlock *block;
247
248   block = uiLayoutAbsoluteBlock(pa->layout);
249   UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
250
251   uvedit_vertex_buttons(C, block);
252 }
253
254 void ED_uvedit_buttons_register(ARegionType *art)
255 {
256   PanelType *pt;
257
258   pt = MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
259   strcpy(pt->idname, "IMAGE_PT_uv");
260   strcpy(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
261   pt->draw = image_panel_uv;
262   pt->poll = image_panel_uv_poll;
263   BLI_addtail(&art->paneltypes, pt);
264 }