/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Contributor(s): Jonathan Smith * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/editors/util/numinput.c * \ingroup edutil */ #include /* fabs */ #include /* for size_t */ #include "BLI_utildefines.h" #include "BLI_string.h" #include "WM_types.h" #include "ED_numinput.h" /* ************************** Functions *************************** */ /* ************************** NUMINPUT **************************** */ void initNumInput(NumInput *n) { n->flag = n->idx = n->idx_max = n->inv[0] = n->inv[1] = n->inv[2] = n->ctrl[0] = n->ctrl[1] = n->ctrl[2] = 0; n->val[0] = n->val[1] = n->val[2] = 0.0f; } void outputNumInput(NumInput *n, char *str) { char cur; char inv[] = "1/"; short i, j; const int ln = NUM_STR_REP_LEN; for (j = 0; j <= n->idx_max; j++) { /* if AFFECTALL and no number typed and cursor not on number, use first number */ if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0) i = 0; else i = j; if (n->idx != i) cur = ' '; else cur = '|'; if (n->inv[i]) inv[0] = '1'; else inv[0] = 0; if (n->val[i] > 1e10f || n->val[i] < -1e10f) BLI_snprintf(&str[j * ln], ln, "%s%.4e%c", inv, n->val[i], cur); else switch (n->ctrl[i]) { case 0: BLI_snprintf(&str[j * ln], ln, "%sNONE%c", inv, cur); break; case 1: case -1: BLI_snprintf(&str[j * ln], ln, "%s%.0f%c", inv, n->val[i], cur); break; case 10: case -10: BLI_snprintf(&str[j * ln], ln, "%s%.f.%c", inv, n->val[i], cur); break; case 100: case -100: BLI_snprintf(&str[j * ln], ln, "%s%.1f%c", inv, n->val[i], cur); break; case 1000: case -1000: BLI_snprintf(&str[j * ln], ln, "%s%.2f%c", inv, n->val[i], cur); break; case 10000: case -10000: BLI_snprintf(&str[j * ln], ln, "%s%.3f%c", inv, n->val[i], cur); break; default: BLI_snprintf(&str[j * ln], ln, "%s%.4e%c", inv, n->val[i], cur); } } } short hasNumInput(NumInput *n) { short i; for (i = 0; i <= n->idx_max; i++) { if (n->ctrl[i]) return 1; } return 0; } /** * \warning \a vec must be set beforehand otherwise we risk uninitialized vars. */ void applyNumInput(NumInput *n, float *vec) { short i, j; if (hasNumInput(n)) { for (j = 0; j <= n->idx_max; j++) { /* if AFFECTALL and no number typed and cursor not on number, use first number */ if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0) i = 0; else i = j; if (n->ctrl[i] == 0 && n->flag & NUM_NULL_ONE) { vec[j] = 1.0f; } else if (n->val[i] == 0.0f && n->flag & NUM_NO_ZERO) { vec[j] = 0.0001f; } else { if (n->inv[i]) { vec[j] = 1.0f / n->val[i]; } else { vec[j] = n->val[i]; } } } } } char handleNumInput(NumInput *n, const wmEvent *event) { float Val = 0; short idx = n->idx, idx_max = n->idx_max; if (event->type == EVT_MODAL_MAP) { switch (event->val) { case NUM_MODAL_INCREMENT_UP: if (!n->ctrl[idx]) n->ctrl[idx] = 1; n->val[idx] += n->increment; break; case NUM_MODAL_INCREMENT_DOWN: if (!n->ctrl[idx]) n->ctrl[idx] = 1; n->val[idx] -= n->increment; break; default: return 0; } } else { switch (event->type) { case BACKSPACEKEY: if (n->ctrl[idx] == 0) { n->val[0] = n->val[1] = n->val[2] = 0.0f; n->ctrl[0] = n->ctrl[1] = n->ctrl[2] = 0; n->inv[0] = n->inv[1] = n->inv[2] = 0; } else { n->val[idx] = 0.0f; n->ctrl[idx] = 0; n->inv[idx] = 0; } break; case PERIODKEY: case PADPERIOD: if (n->flag & NUM_NO_FRACTION) return 0; switch (n->ctrl[idx]) { case 0: case 1: n->ctrl[idx] = 10; break; case -1: n->ctrl[idx] = -10; } break; case PADMINUS: if (event->alt) break; case MINUSKEY: if (n->flag & NUM_NO_NEGATIVE) return 0; if (n->ctrl[idx]) { n->ctrl[idx] *= -1; n->val[idx] *= -1; } else n->ctrl[idx] = -1; break; case PADSLASHKEY: case SLASHKEY: if (n->flag & NUM_NO_FRACTION) return 0; n->inv[idx] = !n->inv[idx]; break; case TABKEY: if (idx_max == 0) return 0; idx++; if (idx > idx_max) idx = 0; n->idx = idx; break; case PAD9: case NINEKEY: Val += 1.0f; case PAD8: case EIGHTKEY: Val += 1.0f; case PAD7: case SEVENKEY: Val += 1.0f; case PAD6: case SIXKEY: Val += 1.0f; case PAD5: case FIVEKEY: Val += 1.0f; case PAD4: case FOURKEY: Val += 1.0f; case PAD3: case THREEKEY: Val += 1.0f; case PAD2: case TWOKEY: Val += 1.0f; case PAD1: case ONEKEY: Val += 1.0f; case PAD0: case ZEROKEY: if (!n->ctrl[idx]) n->ctrl[idx] = 1; if (fabsf(n->val[idx]) > 9999999.0f) { /* pass */ } else if (n->ctrl[idx] == 1) { n->val[idx] *= 10; n->val[idx] += Val; } else if (n->ctrl[idx] == -1) { n->val[idx] *= 10; n->val[idx] -= Val; } else { /* float resolution breaks when over six digits after comma */ if (ABS(n->ctrl[idx]) < 10000000) { n->val[idx] += Val / (float)n->ctrl[idx]; n->ctrl[idx] *= 10; } } break; default: return 0; } } // printf("%f\n", n->val[idx]); /* REDRAW SINCE NUMBERS HAVE CHANGED */ return 1; }