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