code cleanup: minor transform refactor
[blender.git] / source / blender / editors / util / numinput.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Jonathan Smith
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/util/numinput.c
24  *  \ingroup edutil
25  */
26
27
28 #include <math.h>           /* fabs */
29 #include <stdio.h>          /* for size_t */
30
31 #include "BLI_utildefines.h"
32 #include "BLI_string.h"
33
34 #include "WM_types.h"
35
36 #include "ED_numinput.h"
37
38 /* ************************** Functions *************************** */
39
40 /* ************************** NUMINPUT **************************** */
41
42 void initNumInput(NumInput *n)
43 {
44         n->flag     =
45         n->idx      =
46         n->idx_max  =
47         n->inv[0]   =
48         n->inv[1]   =
49         n->inv[2]   =
50         n->ctrl[0]  = 
51         n->ctrl[1]  = 
52         n->ctrl[2]  = 0;
53
54         n->val[0]   = 
55         n->val[1]   = 
56         n->val[2]   = 0.0f;
57 }
58
59 void outputNumInput(NumInput *n, char *str)
60 {
61         char cur;
62         char inv[] = "1/";
63         short i, j;
64         const int ln = NUM_STR_REP_LEN;
65
66         for (j = 0; j <= n->idx_max; j++) {
67                 /* if AFFECTALL and no number typed and cursor not on number, use first number */
68                 if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
69                         i = 0;
70                 else
71                         i = j;
72
73                 if (n->idx != i)
74                         cur = ' ';
75                 else
76                         cur = '|';
77
78                 if (n->inv[i])
79                         inv[0] = '1';
80                 else
81                         inv[0] = 0;
82
83                 if (n->val[i] > 1e10f || n->val[i] < -1e10f)
84                         BLI_snprintf(&str[j * ln], ln, "%s%.4e%c", inv, n->val[i], cur);
85                 else
86                         switch (n->ctrl[i]) {
87                                 case 0:
88                                         BLI_snprintf(&str[j * ln], ln, "%sNONE%c", inv, cur);
89                                         break;
90                                 case 1:
91                                 case -1:
92                                         BLI_snprintf(&str[j * ln], ln, "%s%.0f%c", inv, n->val[i], cur);
93                                         break;
94                                 case 10:
95                                 case -10:
96                                         BLI_snprintf(&str[j * ln], ln, "%s%.f.%c", inv, n->val[i], cur);
97                                         break;
98                                 case 100:
99                                 case -100:
100                                         BLI_snprintf(&str[j * ln], ln, "%s%.1f%c", inv, n->val[i], cur);
101                                         break;
102                                 case 1000:
103                                 case -1000:
104                                         BLI_snprintf(&str[j * ln], ln, "%s%.2f%c", inv, n->val[i], cur);
105                                         break;
106                                 case 10000:
107                                 case -10000:
108                                         BLI_snprintf(&str[j * ln], ln, "%s%.3f%c", inv, n->val[i], cur);
109                                         break;
110                                 default:
111                                         BLI_snprintf(&str[j * ln], ln, "%s%.4e%c", inv, n->val[i], cur);
112                                         break;
113                         }
114         }
115 }
116
117 bool hasNumInput(const NumInput *n)
118 {
119         short i;
120
121         for (i = 0; i <= n->idx_max; i++) {
122                 if (n->ctrl[i])
123                         return true;
124         }
125
126         return false;
127 }
128
129 /**
130  * \warning \a vec must be set beforehand otherwise we risk uninitialized vars.
131  */
132 void applyNumInput(NumInput *n, float *vec)
133 {
134         short i, j;
135
136         if (hasNumInput(n)) {
137                 for (j = 0; j <= n->idx_max; j++) {
138                         /* if AFFECTALL and no number typed and cursor not on number, use first number */
139                         if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
140                                 i = 0;
141                         else
142                                 i = j;
143
144                         if (n->ctrl[i] == 0 && n->flag & NUM_NULL_ONE) {
145                                 vec[j] = 1.0f;
146                         }
147                         else if (n->val[i] == 0.0f && n->flag & NUM_NO_ZERO) {
148                                 vec[j] = 0.0001f;
149                         }
150                         else {
151                                 if (n->inv[i]) {
152                                         vec[j] = 1.0f / n->val[i];
153                                 }
154                                 else {
155                                         vec[j] = n->val[i];
156                                 }
157                         }
158                 }
159         }
160 }
161
162 bool handleNumInput(NumInput *n, const wmEvent *event)
163 {
164         float Val = 0;
165         short idx = n->idx, idx_max = n->idx_max;
166
167         if (event->type == EVT_MODAL_MAP) {
168                 switch (event->val) {
169                         case NUM_MODAL_INCREMENT_UP:
170                                 if (!n->ctrl[idx])
171                                         n->ctrl[idx] = 1;
172
173                                 n->val[idx] += n->increment;
174                                 break;
175                         case NUM_MODAL_INCREMENT_DOWN:
176                                 if (!n->ctrl[idx])
177                                         n->ctrl[idx] = 1;
178
179                                 n->val[idx] -= n->increment;
180                                 break;
181                         default:
182                                 return 0;
183                 }
184         }
185         else {
186                 switch (event->type) {
187                         case BACKSPACEKEY:
188                                 if (n->ctrl[idx] == 0) {
189                                         n->val[0]       =
190                                             n->val[1]   =
191                                             n->val[2]   = 0.0f;
192                                         n->ctrl[0]      =
193                                             n->ctrl[1]  =
194                                             n->ctrl[2]  = 0;
195                                         n->inv[0]       =
196                                             n->inv[1]   =
197                                             n->inv[2]   = 0;
198                                 }
199                                 else {
200                                         n->val[idx] = 0.0f;
201                                         n->ctrl[idx] = 0;
202                                         n->inv[idx] = 0;
203                                 }
204                                 break;
205                         case PERIODKEY: case PADPERIOD:
206                                 if (n->flag & NUM_NO_FRACTION)
207                                         return 0;
208
209                                 switch (n->ctrl[idx]) {
210                                         case 0:
211                                         case 1:
212                                                 n->ctrl[idx] = 10;
213                                                 break;
214                                         case -1:
215                                                 n->ctrl[idx] = -10;
216                                                 break;
217                                 }
218                                 break;
219                         case PADMINUS:
220                                 if (event->alt)
221                                         break;
222                                 /* fall-through */
223                         case MINUSKEY:
224                                 if (n->flag & NUM_NO_NEGATIVE)
225                                         return 0;
226
227                                 if (n->ctrl[idx]) {
228                                         n->ctrl[idx] *= -1;
229                                         n->val[idx] *= -1;
230                                 }
231                                 else
232                                         n->ctrl[idx] = -1;
233                                 break;
234                         case PADSLASHKEY: case SLASHKEY:
235                                 if (n->flag & NUM_NO_FRACTION)
236                                         return 0;
237
238                                 n->inv[idx] = !n->inv[idx];
239                                 break;
240                         case TABKEY:
241                                 if (idx_max == 0)
242                                         return 0;
243
244                                 idx++;
245                                 if (idx > idx_max)
246                                         idx = 0;
247                                 n->idx = idx;
248                                 break;
249                         case PAD9: case NINEKEY:
250                                 Val += 1.0f;
251                                 /* fall-through */
252                         case PAD8: case EIGHTKEY:
253                                 Val += 1.0f;
254                                 /* fall-through */
255                         case PAD7: case SEVENKEY:
256                                 Val += 1.0f;
257                                 /* fall-through */
258                         case PAD6: case SIXKEY:
259                                 Val += 1.0f;
260                                 /* fall-through */
261                         case PAD5: case FIVEKEY:
262                                 Val += 1.0f;
263                                 /* fall-through */
264                         case PAD4: case FOURKEY:
265                                 Val += 1.0f;
266                                 /* fall-through */
267                         case PAD3: case THREEKEY:
268                                 Val += 1.0f;
269                                 /* fall-through */
270                         case PAD2: case TWOKEY:
271                                 Val += 1.0f;
272                                 /* fall-through */
273                         case PAD1: case ONEKEY:
274                                 Val += 1.0f;
275                                 /* fall-through */
276                         case PAD0: case ZEROKEY:
277                                 if (!n->ctrl[idx])
278                                         n->ctrl[idx] = 1;
279
280                                 if (fabsf(n->val[idx]) > 9999999.0f) {
281                                         /* pass */
282                                 }
283                                 else if (n->ctrl[idx] == 1) {
284                                         n->val[idx] *= 10;
285                                         n->val[idx] += Val;
286                                 }
287                                 else if (n->ctrl[idx] == -1) {
288                                         n->val[idx] *= 10;
289                                         n->val[idx] -= Val;
290                                 }
291                                 else {
292                                         /* float resolution breaks when over six digits after comma */
293                                         if (ABS(n->ctrl[idx]) < 10000000) {
294                                                 n->val[idx] += Val / (float)n->ctrl[idx];
295                                                 n->ctrl[idx] *= 10;
296                                         }
297                                 }
298                                 break;
299                         default:
300                                 return 0;
301                 }
302         }
303         
304         // printf("%f\n", n->val[idx]);
305
306         /* REDRAW SINCE NUMBERS HAVE CHANGED */
307         return 1;
308 }