diff options
-rw-r--r-- | source/blender/blenkernel/BKE_unit.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 43 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_markers.c | 10 | ||||
-rw-r--r-- | source/blender/editors/include/ED_numinput.h | 55 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bevel.c | 123 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_inset.c | 255 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_loopcut.c | 249 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 974 | ||||
-rw-r--r-- | source/blender/editors/util/CMakeLists.txt | 5 | ||||
-rw-r--r-- | source/blender/editors/util/SConscript | 4 | ||||
-rw-r--r-- | source/blender/editors/util/numinput.c | 489 |
11 files changed, 1270 insertions, 939 deletions
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index 6b5ce5e1d21..133f3d0dfbc 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -34,7 +34,7 @@ extern "C" { /* in all cases the value is assumed to be scaled by the user preference */ /* humanly readable representation of a value in units (used for button drawing) */ -void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad); +size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad); /* replace units with values, used before python button evaluation */ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 17aad7a5a2c..632ac6234b2 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -260,9 +260,12 @@ static struct bUnitCollection buNaturalTimeCollection = {buNaturalTimeDef, 3, 0, static struct bUnitDef buNaturalRotDef[] = { - {"degree", "degrees", "°", NULL, "Degrees", M_PI / 180.0, 0.0, B_UNIT_DEF_NONE}, -// {"radian", "radians", "r", NULL, "Radians", 1.0, 0.0, B_UNIT_DEF_NONE}, -// {"turn", "turns", "t", NULL, "Turns", 1.0/(M_PI*2.0), 0.0,B_UNIT_DEF_NONE}, + {"degree", "degrees", "°", "d", "Degrees", M_PI / 180.0, 0.0, B_UNIT_DEF_NONE}, + /* arcminutes/arcseconds are used in Astronomy/Navigation areas... */ + {"arcminute", "arcminutes", "'", NULL, "Arcminutes", (M_PI / 180.0) / 60.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"arcsecond", "arcseconds", "\"", NULL, "Arcseconds", (M_PI / 180.0) / 3600.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"radian", "radians", "r", NULL, "Radians", 1.0, 0.0, B_UNIT_DEF_NONE}, +// {"turn", "turns", "t", NULL, "Turns", 1.0 / (M_PI * 2.0), 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef) / sizeof(bUnitDef)}; @@ -340,12 +343,12 @@ static void unit_dual_convert(double value, bUnitCollection *usys, bUnitDef **un *unit_b = unit_best_fit(*value_b, usys, *unit_a, 1); } -static int unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, - /* non exposed options */ - bUnitDef *unit, char pad) +static size_t unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, + /* non exposed options */ + bUnitDef *unit, char pad) { double value_conv; - int len, i; + size_t len, i; if (unit) { /* use unit without finding the best one */ @@ -413,8 +416,10 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC return i; } -/* Used for drawing number buttons, try keep fast */ -void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad) +/* Used for drawing number buttons, try keep fast. + * Return the length of the generated string. + */ +size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad) { bUnitCollection *usys = unit_get_system(system, type); @@ -430,20 +435,21 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, /* check the 2 is a smaller unit */ if (unit_b > unit_a) { - int i = unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); + size_t i; + i = unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); /* is there enough space for at least 1 char of the next unit? */ if (i + 2 < len_max) { str[i++] = ' '; /* use low precision since this is a smaller unit */ - unit_as_string(str + i, len_max - i, value_b, prec ? 1 : 0, usys, unit_b, '\0'); + i += unit_as_string(str + i, len_max - i, value_b, prec ? 1 : 0, usys, unit_b, '\0'); } - return; + return i; } } - unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0'); + return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0'); } BLI_INLINE int isalpha_or_utf8(const int ch) @@ -606,15 +612,8 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca return 0; } - { /* make lowercase */ - int i; - char *ch = str; - - for (i = 0; (i < len_max) && (*ch != '\0'); i++, ch++) { - if ((*ch >= 'A') && (*ch <= 'Z')) - *ch += ('a' - 'A'); - } - } + /* make lowercase */ + BLI_ascii_strtolower(str, len_max); for (unit = usys->units; unit->name; unit++) { /* in case there are multiple instances */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 4af3c051c6d..e65ca3d20be 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -45,6 +45,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_unit.h" #include "RNA_access.h" #include "RNA_define.h" @@ -603,6 +604,7 @@ typedef struct MarkerMove { /* return 0 if not OK */ static int ed_marker_move_init(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ListBase *markers = ED_context_get_markers(C); MarkerMove *mm; TimeMarker *marker; @@ -623,8 +625,10 @@ static int ed_marker_move_init(bContext *C, wmOperator *op) initNumInput(&mm->num); mm->num.idx_max = 0; /* one axis */ - mm->num.flag |= NUM_NO_FRACTION; - mm->num.increment = 1.0f; + mm->num.val_flag[0] |= NUM_NO_FRACTION; + mm->num.unit_sys = scene->unit.system; + /* No time unit supporting frames currently... */ + mm->num.unit_type[0] = B_UNIT_NONE; for (a = 0, marker = markers->first; marker; marker = marker->next) { if (marker->flag & SELECT) { @@ -832,7 +836,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even } if (event->val == KM_PRESS) { - if (handleNumInput(&mm->num, event)) { + if (handleNumInput(C, &mm->num, event)) { char str_tx[NUM_STR_REP_LEN]; float value = RNA_int_get(op->ptr, "frames"); applyNumInput(&mm->num, &value); diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h index f46332c9a82..e44dab7bff0 100644 --- a/source/blender/editors/include/ED_numinput.h +++ b/source/blender/editors/include/ED_numinput.h @@ -27,40 +27,49 @@ #ifndef __ED_NUMINPUT_H__ #define __ED_NUMINPUT_H__ -/* - * The ctrl value has different meaning: - * 0 : No value has been typed - * - * otherwise, |value| - 1 is where the cursor is located after the period - * Positive : number is positive - * Negative : number is negative - */ +#define NUM_STR_REP_LEN 64 +#define NUM_MAX_ELEMENTS 3 typedef struct NumInput { - short idx; - short idx_max; - short flag; /* Different flags to indicate different behaviors */ - char inv[3]; /* If the value is inverted or not */ - float val[3]; /* Direct value of the input */ - int ctrl[3]; /* Control to indicate what to do with the numbers that are typed */ - float increment; + short idx_max; /* idx_max < NUM_MAX_ELEMENTS */ + int unit_sys; + int unit_type[NUM_MAX_ELEMENTS]; /* Each value can have a different type */ + bool unit_use_radians; + + short flag; /* Flags affecting all values' behavior */ + short val_flag[NUM_MAX_ELEMENTS]; /* Per-value flags */ + float val[NUM_MAX_ELEMENTS]; /* Direct value of the input */ + float val_org[NUM_MAX_ELEMENTS]; /* Original value of the input, for reset */ + float val_inc[NUM_MAX_ELEMENTS]; /* Increment steps */ + + short idx; /* Active element/value */ + char str[NUM_STR_REP_LEN]; /* String as typed by user for edited value (we assume ASCII world!) */ + /* Current position of cursor in edited value str (first byte of "current" letter, so 0 for an empty str) */ + int str_cur; } NumInput; -/* NUMINPUT FLAGS */ -#define NUM_NULL_ONE 2 -#define NUM_NO_NEGATIVE 4 -#define NUM_NO_ZERO 8 -#define NUM_NO_FRACTION 16 -#define NUM_AFFECT_ALL 32 +/* NumInput.flag */ +enum { + NUM_AFFECT_ALL = (1 << 0), +}; + +/* NumInput.val_flag[] */ +enum { + /* Public! */ + NUM_NULL_ONE = (1 << 0), + NUM_NO_NEGATIVE = (1 << 1), + NUM_NO_ZERO = (1 << 2), + NUM_NO_FRACTION = (1 << 3), + /* (1 << 9) and above are reserved for internal flags! */ +}; /*********************** NumInput ********************************/ void initNumInput(NumInput *n); -#define NUM_STR_REP_LEN 20 /* str must be NUM_STR_LEN * (idx_max + 1) length. */ void outputNumInput(NumInput *n, char *str); bool hasNumInput(const NumInput *n); void applyNumInput(NumInput *n, float *vec); -bool handleNumInput(NumInput *n, const struct wmEvent *event); +bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event); #define NUM_MODAL_INCREMENT_UP 18 #define NUM_MODAL_INCREMENT_DOWN 19 diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index ddb58cd6c7b..9a6131f76e9 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -36,6 +36,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_editmesh.h" +#include "BKE_unit.h" #include "RNA_define.h" #include "RNA_access.h" @@ -74,18 +75,23 @@ typedef struct { static void edbm_bevel_update_header(wmOperator *op, bContext *C) { - const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RMB), Offset: %s, Segments: %d"); + const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Offset: %s, Segments: %d"); char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); if (sa) { + BevelData *opdata = op->customdata; char offset_str[NUM_STR_REP_LEN]; - BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); - BLI_snprintf(msg, HEADER_LENGTH, str, - offset_str, - RNA_int_get(op->ptr, "segments") - ); + + if (hasNumInput(&opdata->num_input)) { + outputNumInput(&opdata->num_input, offset_str); + } + else { + BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); + } + + BLI_snprintf(msg, HEADER_LENGTH, str, offset_str, RNA_int_get(op->ptr, "segments")); ED_area_headerprint(sa, msg); } @@ -94,6 +100,7 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Object *obedit = CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BevelData *opdata; @@ -108,7 +115,10 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) opdata->shift_factor = -1.0f; initNumInput(&opdata->num_input); - opdata->num_input.flag = NUM_NO_NEGATIVE; + opdata->num_input.idx_max = 0; + opdata->num_input.val_flag[0] |= NUM_NO_NEGATIVE; + opdata->num_input.unit_sys = scene->unit.system; + opdata->num_input.unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */ /* avoid the cost of allocating a bm copy */ if (is_modal) { @@ -306,10 +316,9 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) BevelData *opdata = op->customdata; int segments = RNA_int_get(op->ptr, "segments"); - if (event->val == KM_PRESS) { - /* Try to handle numeric inputs... */ - - if (handleNumInput(&opdata->num_input, event)) { + if (event->val == KM_PRESS && hasNumInput(&opdata->num_input)) { + /* Modal numinput active, try to handle numeric inputs first... */ + if (handleNumInput(C, &opdata->num_input, event)) { float value = RNA_float_get(op->ptr, "offset"); applyNumInput(&opdata->num_input, &value); RNA_float_set(op->ptr, "offset", value); @@ -318,51 +327,73 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } } + else { + bool handled = false; + switch (event->type) { + case ESCKEY: + case RIGHTMOUSE: + edbm_bevel_cancel(C, op); + return OPERATOR_CANCELLED; + + case MOUSEMOVE: + if (!hasNumInput(&opdata->num_input)) { + const float factor = edbm_bevel_mval_factor(op, event); + RNA_float_set(op->ptr, "offset", factor); + + edbm_bevel_calc(op); + edbm_bevel_update_header(op, C); + handled = true; + } + break; + + case LEFTMOUSE: + case PADENTER: + case RETKEY: + edbm_bevel_calc(op); + edbm_bevel_exit(C, op); + return OPERATOR_FINISHED; - switch (event->type) { - case ESCKEY: - case RIGHTMOUSE: - edbm_bevel_cancel(C, op); - return OPERATOR_CANCELLED; + /* Note this will prevent padplus and padminus to ever activate modal numinput. + * This is not really an issue though, as we only expect positive values here... + * Else we could force them to only modify segments number when shift is pressed, or so. + */ - case MOUSEMOVE: - if (!hasNumInput(&opdata->num_input)) { - const float factor = edbm_bevel_mval_factor(op, event); - RNA_float_set(op->ptr, "offset", factor); + case WHEELUPMOUSE: /* change number of segments */ + case PADPLUSKEY: + if (event->val == KM_RELEASE) + break; + segments++; + RNA_int_set(op->ptr, "segments", segments); edbm_bevel_calc(op); edbm_bevel_update_header(op, C); - } - break; - - case LEFTMOUSE: - case PADENTER: - case RETKEY: - edbm_bevel_calc(op); - edbm_bevel_exit(C, op); - return OPERATOR_FINISHED; - - case WHEELUPMOUSE: /* change number of segments */ - case PADPLUSKEY: - if (event->val == KM_RELEASE) + handled = true; break; - segments++; - RNA_int_set(op->ptr, "segments", segments); - edbm_bevel_calc(op); - edbm_bevel_update_header(op, C); - break; + case WHEELDOWNMOUSE: /* change number of segments */ + case PADMINUS: + if (event->val == KM_RELEASE) + break; - case WHEELDOWNMOUSE: /* change number of segments */ - case PADMINUS: - if (event->val == KM_RELEASE) + segments = max_ii(segments - 1, 1); + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(op); + edbm_bevel_update_header(op, C); + handled = true; break; + } - segments = max_ii(segments - 1, 1); - RNA_int_set(op->ptr, "segments", segments); - edbm_bevel_calc(op); - edbm_bevel_update_header(op, C); - break; + if (!handled && event->val == KM_PRESS) { + /* Modal numinput inactive, try to handle numeric inputs last... */ + if (handleNumInput(C, &opdata->num_input, event)) { + float value = RNA_float_get(op->ptr, "offset"); + applyNumInput(&opdata->num_input, &value); + RNA_float_set(op->ptr, "offset", value); + edbm_bevel_calc(op); + edbm_bevel_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } + } } return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 137554459ce..5f23a5deb97 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -36,6 +36,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_editmesh.h" +#include "BKE_unit.h" #include "RNA_define.h" #include "RNA_access.h" @@ -110,6 +111,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C) static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) { InsetData *opdata; + Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -129,6 +131,9 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) initNumInput(&opdata->num_input); opdata->num_input.idx_max = 1; /* Two elements. */ + opdata->num_input.unit_sys = scene->unit.system; + opdata->num_input.unit_type[0] = B_UNIT_LENGTH; + opdata->num_input.unit_type[1] = B_UNIT_LENGTH; if (is_modal) { View3D *v3d = CTX_wm_view3d(C); @@ -291,10 +296,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event) { InsetData *opdata = op->customdata; - if (event->val == KM_PRESS) { - /* Try to handle numeric inputs... */ - - if (handleNumInput(&opdata->num_input, event)) { + if (event->val == KM_PRESS && hasNumInput(&opdata->num_input)) { + /* Modal numinput active, try to handle numeric inputs first... */ + if (handleNumInput(C, &opdata->num_input, event)) { float amounts[2] = {RNA_float_get(op->ptr, "thickness"), RNA_float_get(op->ptr, "depth")}; applyNumInput(&opdata->num_input, amounts); @@ -312,134 +316,163 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event) } } } + else { + bool handled = false; + switch (event->type) { + case ESCKEY: + case RIGHTMOUSE: + edbm_inset_cancel(C, op); + return OPERATOR_CANCELLED; - switch (event->type) { - case ESCKEY: - case RIGHTMOUSE: - edbm_inset_cancel(C, op); - return OPERATOR_CANCELLED; - - case MOUSEMOVE: - if (!hasNumInput(&opdata->num_input)) { - float mdiff[2]; - float amount; - - mdiff[0] = opdata->mcenter[0] - event->mval[0]; - mdiff[1] = opdata->mcenter[1] - event->mval[1]; - - if (opdata->modify_depth) - amount = opdata->old_depth + ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); - else - amount = opdata->old_thickness - ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); - - /* Fake shift-transform... */ - if (opdata->shift) - amount = (amount - opdata->shift_amount) * 0.1f + opdata->shift_amount; - - if (opdata->modify_depth) - RNA_float_set(op->ptr, "depth", amount); - else { - amount = max_ff(amount, 0.0f); - RNA_float_set(op->ptr, "thickness", amount); + case MOUSEMOVE: + if (!hasNumInput(&opdata->num_input)) { + float mdiff[2]; + float amount; + + mdiff[0] = opdata->mcenter[0] - event->mval[0]; + mdiff[1] = opdata->mcenter[1] - event->mval[1]; + + if (opdata->modify_depth) + amount = opdata->old_depth + ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); + else + amount = opdata->old_thickness - ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); + + /* Fake shift-transform... */ + if (opdata->shift) + amount = (amount - opdata->shift_amount) * 0.1f + opdata->shift_amount; + + if (opdata->modify_depth) + RNA_float_set(op->ptr, "depth", amount); + else { + amount = max_ff(amount, 0.0f); + RNA_float_set(op->ptr, "thickness", amount); + } + + if (edbm_inset_calc(op)) + edbm_inset_update_header(op, C); + else { + edbm_inset_cancel(C, op); + return OPERATOR_CANCELLED; + } + handled = true; + } + break; + + case LEFTMOUSE: + case PADENTER: + case RETKEY: + edbm_inset_calc(op); + edbm_inset_exit(C, op); + return OPERATOR_FINISHED; + + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + if (event->val == KM_PRESS) { + if (opdata->modify_depth) + opdata->shift_amount = RNA_float_get(op->ptr, "depth"); + else + opdata->shift_amount = RNA_float_get(op->ptr, "thickness"); + opdata->shift = true; + handled = true; } - - if (edbm_inset_calc(op)) - edbm_inset_update_header(op, C); else { - edbm_inset_cancel(C, op); - return OPERATOR_CANCELLED; + opdata->shift_amount = 0.0f; + opdata->shift = false; + handled = true; } - } - break; - - case LEFTMOUSE: - case PADENTER: - case RETKEY: - edbm_inset_calc(op); - edbm_inset_exit(C, op); - return OPERATOR_FINISHED; - - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - if (event->val == KM_PRESS) { - if (opdata->modify_depth) - opdata->shift_amount = RNA_float_get(op->ptr, "depth"); - else - opdata->shift_amount = RNA_float_get(op->ptr, "thickness"); - opdata->shift = true; - } - else { - opdata->shift_amount = 0.0f; - opdata->shift = false; - } - break; - - case LEFTCTRLKEY: - case RIGHTCTRLKEY: - { - float mlen[2]; + break; - mlen[0] = opdata->mcenter[0] - event->mval[0]; - mlen[1] = opdata->mcenter[1] - event->mval[1]; - - if (event->val == KM_PRESS) { - opdata->old_thickness = RNA_float_get(op->ptr, "thickness"); - if (opdata->shift) - opdata->shift_amount = opdata->old_thickness; - opdata->modify_depth = true; - } - else { - opdata->old_depth = RNA_float_get(op->ptr, "depth"); - if (opdata->shift) - opdata->shift_amount = opdata->old_depth; - opdata->modify_depth = false; - } - opdata->initial_length = len_v2(mlen); + case LEFTCTRLKEY: + case RIGHTCTRLKEY: + { + float mlen[2]; - edbm_inset_update_header(op, C); - break; - } + mlen[0] = opdata->mcenter[0] - event->mval[0]; + mlen[1] = opdata->mcenter[1] - event->mval[1]; - case OKEY: - if (event->val == KM_PRESS) { - const bool use_outset = RNA_boolean_get(op->ptr, "use_outset"); - RNA_boolean_set(op->ptr, "use_outset", !use_outset); - if (edbm_inset_calc(op)) { - edbm_inset_update_header(op, C); + if (event->val == KM_PRESS) { + opdata->old_thickness = RNA_float_get(op->ptr, "thickness"); + if (opdata->shift) + opdata->shift_amount = opdata->old_thickness; + opdata->modify_depth = true; } else { - edbm_inset_cancel(C, op); - return OPERATOR_CANCELLED; + opdata->old_depth = RNA_float_get(op->ptr, "depth"); + if (opdata->shift) + opdata->shift_amount = opdata->old_depth; + opdata->modify_depth = false; } + opdata->initial_length = len_v2(mlen); + + edbm_inset_update_header(op, C); + handled = true; + break; } - break; - case BKEY: - if (event->val == KM_PRESS) { - const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary"); - RNA_boolean_set(op->ptr, "use_boundary", !use_boundary); - if (edbm_inset_calc(op)) { - edbm_inset_update_header(op, C); + + case OKEY: + if (event->val == KM_PRESS) { + const bool use_outset = RNA_boolean_get(op->ptr, "use_outset"); + RNA_boolean_set(op->ptr, "use_outset", !use_outset); + if (edbm_inset_calc(op)) { + edbm_inset_update_header(op, C); + } + else { + edbm_inset_cancel(C, op); + return OPERATOR_CANCELLED; + } + handled = true; } - else { - edbm_inset_cancel(C, op); - return OPERATOR_CANCELLED; + break; + case BKEY: + if (event->val == KM_PRESS) { + const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary"); + RNA_boolean_set(op->ptr, "use_boundary", !use_boundary); + if (edbm_inset_calc(op)) { + edbm_inset_update_header(op, C); + } + else { + edbm_inset_cancel(C, op); + return OPERATOR_CANCELLED; + } + handled = true; } - } - break; - case IKEY: - if (event->val == KM_PRESS) { - const bool use_individual = RNA_boolean_get(op->ptr, "use_individual"); - RNA_boolean_set(op->ptr, "use_individual", !use_individual); + break; + case IKEY: + if (event->val == KM_PRESS) { + const bool use_individual = RNA_boolean_get(op->ptr, "use_individual"); + RNA_boolean_set(op->ptr, "use_individual", !use_individual); + if (edbm_inset_calc(op)) { + edbm_inset_update_header(op, C); + } + else { + edbm_inset_cancel(C, op); + return OPERATOR_CANCELLED; + } + handled = true; + } + break; + } + + if (!handled && event->val == KM_PRESS) { + /* Modal numinput inactive, try to handle numeric inputs last... */ + if (handleNumInput(C, &opdata->num_input, event)) { + float amounts[2] = {RNA_float_get(op->ptr, "thickness"), + RNA_float_get(op->ptr, "depth")}; + applyNumInput(&opdata->num_input, amounts); + amounts[0] = max_ff(amounts[0], 0.0f); + RNA_float_set(op->ptr, "thickness", amounts[0]); + RNA_float_set(op->ptr, "depth", amounts[1]); + if (edbm_inset_calc(op)) { edbm_inset_update_header(op, C); + return OPERATOR_RUNNING_MODAL; } else { edbm_inset_cancel(C, op); return OPERATOR_CANCELLED; } } - break; - + } } return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 9223f6d9450..fd24981bde0 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -43,6 +43,7 @@ #include "BKE_report.h" #include "BKE_editmesh.h" #include "BKE_DerivedMesh.h" +#include "BKE_unit.h" #include "BIF_gl.h" @@ -392,6 +393,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) static int ringsel_init(bContext *C, wmOperator *op, bool do_cut) { RingSelOpData *lcd; + Scene *scene = CTX_data_scene(C); /* alloc new customdata */ lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data"); @@ -405,8 +407,12 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut) lcd->do_cut = do_cut; initNumInput(&lcd->num); - lcd->num.idx_max = 0; - lcd->num.flag |= NUM_NO_NEGATIVE | NUM_NO_FRACTION; + lcd->num.idx_max = 1; + lcd->num.val_flag[0] |= NUM_NO_NEGATIVE | NUM_NO_FRACTION; + /* No specific flags for smoothness. */ + lcd->num.unit_sys = scene->unit.system; + lcd->num.unit_type[0] = B_UNIT_NONE; + lcd->num.unit_type[1] = B_UNIT_NONE; /* XXX, temp, workaround for [# ] */ EDBM_mesh_ensure_valid_dm_hack(CTX_data_scene(C), lcd->em); @@ -529,126 +535,163 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) view3d_operator_needs_opengl(C); - switch (event->type) { - case RETKEY: - case PADENTER: - case LEFTMOUSE: /* confirm */ // XXX hardcoded - if (event->val == KM_PRESS) { - /* finish */ + /* using the keyboard to input the number of cuts */ + if (event->val == KM_PRESS && hasNumInput(&lcd->num)) { + /* Modal numinput active, try to handle numeric inputs first... */ + if (handleNumInput(C, &lcd->num, event)) { + float values[2] = {(float)cuts, smoothness}; + applyNumInput(&lcd->num, values); + + /* allow zero so you can backspace and type in a value + * otherwise 1 as minimum would make more sense */ + cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX); + smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX); + + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = true; + RNA_float_set(op->ptr, "smoothness", smoothness); + + ED_region_tag_redraw(lcd->ar); + } + } + else { + bool handled = false; + switch (event->type) { + case RETKEY: + case PADENTER: + case LEFTMOUSE: /* confirm */ // XXX hardcoded + if (event->val == KM_PRESS) { + /* finish */ + ED_region_tag_redraw(lcd->ar); + ED_area_headerprint(CTX_wm_area(C), NULL); + + if (lcd->eed) { + /* set for redo */ + BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE); + RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed)); + + /* execute */ + ringsel_finish(C, op); + ringsel_exit(C, op); + } + else { + ringcut_cancel(C, op); + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; + } + + ED_region_tag_redraw(lcd->ar); + handled = true; + break; + case RIGHTMOUSE: /* abort */ // XXX hardcoded ED_region_tag_redraw(lcd->ar); + ringsel_exit(C, op); ED_area_headerprint(CTX_wm_area(C), NULL); - if (lcd->eed) { - /* set for redo */ - BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE); - RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed)); - - /* execute */ - ringsel_finish(C, op); - ringsel_exit(C, op); - } - else { + return OPERATOR_FINISHED; + case ESCKEY: + if (event->val == KM_RELEASE) { + /* cancel */ + ED_region_tag_redraw(lcd->ar); + ED_area_headerprint(CTX_wm_area(C), NULL); + ringcut_cancel(C, op); return OPERATOR_CANCELLED; } - - return OPERATOR_FINISHED; - } - - ED_region_tag_redraw(lcd->ar); - break; - case RIGHTMOUSE: /* abort */ // XXX hardcoded - ED_region_tag_redraw(lcd->ar); - ringsel_exit(C, op); - ED_area_headerprint(CTX_wm_area(C), NULL); - - return OPERATOR_FINISHED; - case ESCKEY: - if (event->val == KM_RELEASE) { - /* cancel */ + ED_region_tag_redraw(lcd->ar); - ED_area_headerprint(CTX_wm_area(C), NULL); + handled = true; + break; + case PADPLUSKEY: + case PAGEUPKEY: + case WHEELUPMOUSE: /* change number of cuts */ + if (event->val == KM_RELEASE) + break; + if (event->alt == 0) { + cuts++; + cuts = CLAMPIS(cuts, 0, SUBD_CUTS_MAX); + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = true; + } + else { + smoothness = min_ff(smoothness + 0.05f, SUBD_SMOOTH_MAX); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = true; + } - ringcut_cancel(C, op); - return OPERATOR_CANCELLED; - } - - ED_region_tag_redraw(lcd->ar); - break; - case PADPLUSKEY: - case PAGEUPKEY: - case WHEELUPMOUSE: /* change number of cuts */ - if (event->val == KM_RELEASE) + ED_region_tag_redraw(lcd->ar); + handled = true; break; - if (event->alt == 0) { - cuts++; - cuts = CLAMPIS(cuts, 0, SUBD_CUTS_MAX); - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = true; - } - else { - smoothness = min_ff(smoothness + 0.05f, SUBD_SMOOTH_MAX); - RNA_float_set(op->ptr, "smoothness", smoothness); - show_cuts = true; - } - - ED_region_tag_redraw(lcd->ar); - break; - case PADMINUS: - case PAGEDOWNKEY: - case WHEELDOWNMOUSE: /* change number of cuts */ - if (event->val == KM_RELEASE) + case PADMINUS: + case PAGEDOWNKEY: + case WHEELDOWNMOUSE: /* change number of cuts */ + if (event->val == KM_RELEASE) + break; + + if (event->alt == 0) { + cuts = max_ii(cuts - 1, 1); + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = true; + } + else { + smoothness = max_ff(smoothness - 0.05f, -SUBD_SMOOTH_MAX); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = true; + } + + ED_region_tag_redraw(lcd->ar); + handled = true; + break; + case MOUSEMOVE: /* mouse moved somewhere to select another loop */ + { + lcd->vc.mval[0] = event->mval[0]; + lcd->vc.mval[1] = event->mval[1]; + loopcut_mouse_move(lcd, cuts); + + ED_region_tag_redraw(lcd->ar); + handled = true; break; + } + } - if (event->alt == 0) { - cuts = max_ii(cuts - 1, 1); + if (!handled && event->val == KM_PRESS) { + /* Modal numinput inactive, try to handle numeric inputs last... */ + if (handleNumInput(C, &lcd->num, event)) { + float values[2] = {(float)cuts, smoothness}; + applyNumInput(&lcd->num, values); + + /* allow zero so you can backspace and type in a value + * otherwise 1 as minimum would make more sense */ + cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX); + smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX); + RNA_int_set(op->ptr, "number_cuts", cuts); ringsel_find_edge(lcd, cuts); show_cuts = true; - } - else { - smoothness = max_ff(smoothness - 0.05f, -SUBD_SMOOTH_MAX); RNA_float_set(op->ptr, "smoothness", smoothness); - show_cuts = true; + + ED_region_tag_redraw(lcd->ar); } - - ED_region_tag_redraw(lcd->ar); - break; - case MOUSEMOVE: /* mouse moved somewhere to select another loop */ - { - lcd->vc.mval[0] = event->mval[0]; - lcd->vc.mval[1] = event->mval[1]; - loopcut_mouse_move(lcd, cuts); - - ED_region_tag_redraw(lcd->ar); - break; - } - } - - /* using the keyboard to input the number of cuts */ - if (event->val == KM_PRESS) { - /* init as zero so backspace clears */ - - if (handleNumInput(&lcd->num, event)) { - float value = RNA_int_get(op->ptr, "number_cuts"); - applyNumInput(&lcd->num, &value); - - /* allow zero so you can backspace and type in a value - * otherwise 1 as minimum would make more sense */ - cuts = CLAMPIS(value, 0, SUBD_CUTS_MAX); - - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = true; - - ED_region_tag_redraw(lcd->ar); } } - + if (show_cuts) { - char buf[64]; - BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %d, Smooth: %.2f (Alt)"), cuts, smoothness); + char buf[64 + NUM_STR_REP_LEN * 2]; + char str_rep[NUM_STR_REP_LEN * 2]; + if (hasNumInput(&lcd->num)) { + outputNumInput(&lcd->num, str_rep); + } + else { + BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", cuts); + BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", smoothness); + } + BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %s, Smooth: %s (Alt)"), + str_rep, str_rep + NUM_STR_REP_LEN); ED_area_headerprint(CTX_wm_area(C), buf); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f0756a6f86e..35aa3a3f1d7 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -944,8 +944,8 @@ int transformEvent(TransInfo *t, const wmEvent *event) { float mati[3][3] = MAT3_UNITY; char cmode = constraintModeToChar(t); - int handled = 1; - + bool handled = false; + t->redraw |= handleMouseInput(t, &t->mouse, event); if (event->type == MOUSEMOVE) { @@ -957,7 +957,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) // t->redraw |= TREDRAW_SOFT; /* Use this for soft redraw. Might cause flicker in object mode */ t->redraw |= TREDRAW_HARD; - if (t->state == TRANS_STARTING) { t->state = TRANS_RUNNING; } @@ -966,445 +965,503 @@ int transformEvent(TransInfo *t, const wmEvent *event) // Snapping mouse move events t->redraw |= handleSnapping(t, event); + handled = true; } - /* handle modal keymap first */ - if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case TFM_MODAL_CANCEL: - t->state = TRANS_CANCEL; - break; - case TFM_MODAL_CONFIRM: - t->state = TRANS_CONFIRM; - break; - case TFM_MODAL_TRANSLATE: - /* only switch when... */ - if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - resetTransModal(t); - resetTransRestrictions(t); - restoreTransObjects(t); - initTranslation(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - WM_event_add_mousemove(t->context); - } - else if (t->mode == TFM_SEQ_SLIDE) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - } - else { - if (t->obedit && t->obedit->type == OB_MESH) { - if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + else if (event->type == EVT_MODAL_MAP) { + /* Handle modal numinput events first, if already activated. */ + if (hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } + else { + switch (event->val) { + case TFM_MODAL_CANCEL: + t->state = TRANS_CANCEL; + handled = true; + break; + case TFM_MODAL_CONFIRM: + t->state = TRANS_CONFIRM; + handled = true; + break; + case TFM_MODAL_TRANSLATE: + /* only switch when... */ + if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + resetTransModal(t); + resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); + handled = true; + } + else if (t->mode == TFM_SEQ_SLIDE) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else { + if (t->obedit && t->obedit->type == OB_MESH) { + if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + resetTransModal(t); + resetTransRestrictions(t); + restoreTransObjects(t); + + /* first try edge slide */ + initEdgeSlide(t); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + initVertSlide(t); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + WM_event_add_mousemove(t->context); + } + } + else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->mode == TFM_TRANSLATION) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + } + break; + case TFM_MODAL_ROTATE: + /* only switch when... */ + if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { + if (ELEM6(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { resetTransModal(t); resetTransRestrictions(t); - restoreTransObjects(t); - - /* first try edge slide */ - initEdgeSlide(t); - /* if that fails, do vertex slide */ - if (t->state == TRANS_CANCEL) { - t->state = TRANS_STARTING; - initVertSlide(t); + + if (t->mode == TFM_ROTATION) { + restoreTransObjects(t); + initTrackball(t); } - /* vert slide can fail on unconnected vertices (rare but possible) */ - if (t->state == TRANS_CANCEL) { - t->state = TRANS_STARTING; - resetTransRestrictions(t); + else { restoreTransObjects(t); - initTranslation(t); + initRotation(t); } initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; - WM_event_add_mousemove(t->context); + handled = true; } } - else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - if (t->mode == TFM_TRANSLATION) { + break; + case TFM_MODAL_RESIZE: + /* only switch when... */ + if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + resetTransModal(t); + resetTransRestrictions(t); + restoreTransObjects(t); + initResize(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (t->mode == TFM_SHRINKFATTEN) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { restoreTransObjects(t); t->flag ^= T_ALT_TRANSFORM; t->redraw |= TREDRAW_HARD; + handled = true; } } - } - break; - case TFM_MODAL_ROTATE: - /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { - if (ELEM6(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - resetTransModal(t); - resetTransRestrictions(t); - - if (t->mode == TFM_ROTATION) { - restoreTransObjects(t); - initTrackball(t); + break; + + case TFM_MODAL_SNAP_INV_ON: + t->modifiers |= MOD_SNAP_INVERT; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_SNAP_INV_OFF: + t->modifiers &= ~MOD_SNAP_INVERT; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_SNAP_TOGGLE: + t->modifiers ^= MOD_SNAP; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_AXIS_X: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + if (cmode == 'X') { + stopConstraint(t); } else { - restoreTransObjects(t); - initRotation(t); + if (t->flag & T_2D_EDIT) { + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X")); + } + else { + setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X")); + } } - initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; + handled = true; } - } - break; - case TFM_MODAL_RESIZE: - /* only switch when... */ - if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - resetTransModal(t); - resetTransRestrictions(t); - restoreTransObjects(t); - initResize(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - } - else if (t->mode == TFM_SHRINKFATTEN) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - } - else if (t->mode == TFM_RESIZE) { - if (t->options & CTX_MOVIECLIP) { - restoreTransObjects(t); - - t->flag ^= T_ALT_TRANSFORM; + break; + case TFM_MODAL_AXIS_Y: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + if (cmode == 'Y') { + stopConstraint(t); + } + else { + if (t->flag & T_2D_EDIT) { + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y")); + } + else { + setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y")); + } + } t->redraw |= TREDRAW_HARD; + handled = true; } - } - break; - - case TFM_MODAL_SNAP_INV_ON: - t->modifiers |= MOD_SNAP_INVERT; - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_SNAP_INV_OFF: - t->modifiers &= ~MOD_SNAP_INVERT; - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_SNAP_TOGGLE: - t->modifiers ^= MOD_SNAP; - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_AXIS_X: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - if (cmode == 'X') { - stopConstraint(t); + break; + case TFM_MODAL_AXIS_Z: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + if (cmode == 'Z') { + stopConstraint(t); + } + else { + setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z")); + } + t->redraw |= TREDRAW_HARD; + handled = true; } - else { - if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X")); + break; + case TFM_MODAL_PLANE_X: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + if (cmode == 'X') { + stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X")); + setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), IFACE_("locking %s X")); } + t->redraw |= TREDRAW_HARD; + handled = true; } - t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_AXIS_Y: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - if (cmode == 'Y') { - stopConstraint(t); + break; + case TFM_MODAL_PLANE_Y: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + if (cmode == 'Y') { + stopConstraint(t); + } + else { + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), IFACE_("locking %s Y")); + } + t->redraw |= TREDRAW_HARD; + handled = true; } - else { - if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y")); + break; + case TFM_MODAL_PLANE_Z: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + if (cmode == 'Z') { + stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y")); + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), IFACE_("locking %s Z")); } + t->redraw |= TREDRAW_HARD; + handled = true; } - t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_AXIS_Z: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - if (cmode == 'Z') { + break; + case TFM_MODAL_CONS_OFF: + if ((t->flag & T_NO_CONSTRAINT) == 0) { stopConstraint(t); + t->redraw |= TREDRAW_HARD; + handled = true; } - else { - setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z")); - } + break; + case TFM_MODAL_ADD_SNAP: + addSnapPoint(t); t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_PLANE_X: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - if (cmode == 'X') { - stopConstraint(t); - } - else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), IFACE_("locking %s X")); - } + handled = true; + break; + case TFM_MODAL_REMOVE_SNAP: + removeSnapPoint(t); t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_PLANE_Y: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - if (cmode == 'Y') { - stopConstraint(t); + handled = true; + break; + case TFM_MODAL_PROPSIZE: + /* MOUSEPAN usage... */ + if (t->flag & T_PROP_EDIT) { + float fac = 1.0f + 0.005f *(event->y - event->prevy); + t->prop_size *= fac; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; } - else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), IFACE_("locking %s Y")); + break; + case TFM_MODAL_PROPSIZE_UP: + if (t->flag & T_PROP_EDIT) { + t->prop_size *= 1.1f; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; } + break; + case TFM_MODAL_PROPSIZE_DOWN: + if (t->flag & T_PROP_EDIT) { + t->prop_size *= 0.90909090f; + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_EDGESLIDE_UP: + case TFM_MODAL_EDGESLIDE_DOWN: t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_PLANE_Z: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - if (cmode == 'Z') { - stopConstraint(t); + handled = true; + break; + case TFM_MODAL_AUTOIK_LEN_INC: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, 1); + t->redraw |= TREDRAW_HARD; + handled = true; } - else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), IFACE_("locking %s Z")); + break; + case TFM_MODAL_AUTOIK_LEN_DEC: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, -1); + t->redraw |= TREDRAW_HARD; + handled = true; } - t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_CONS_OFF: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - stopConstraint(t); - t->redraw |= TREDRAW_HARD; - } - break; - case TFM_MODAL_ADD_SNAP: - addSnapPoint(t); - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_REMOVE_SNAP: - removeSnapPoint(t); - t->redraw |= TREDRAW_HARD; - break; - - case TFM_MODAL_PROPSIZE: - /* MOUSEPAN usage... */ - if (t->flag & T_PROP_EDIT) { - float fac = 1.0f + 0.005f *(event->y - event->prevy); - t->prop_size *= fac; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); - calculatePropRatio(t); - } - t->redraw |= TREDRAW_HARD; - break; - - case TFM_MODAL_PROPSIZE_UP: - if (t->flag & T_PROP_EDIT) { - t->prop_size *= 1.1f; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); - calculatePropRatio(t); - } - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_PROPSIZE_DOWN: - if (t->flag & T_PROP_EDIT) { - t->prop_size *= 0.90909090f; - calculatePropRatio(t); - } - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_EDGESLIDE_UP: - case TFM_MODAL_EDGESLIDE_DOWN: - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_AUTOIK_LEN_INC: - if (t->flag & T_AUTOIK) - transform_autoik_update(t, 1); - t->redraw |= TREDRAW_HARD; - break; - case TFM_MODAL_AUTOIK_LEN_DEC: - if (t->flag & T_AUTOIK) - transform_autoik_update(t, -1); - t->redraw |= TREDRAW_HARD; - break; - default: - handled = 0; - break; - } + break; + default: + break; + } - /* Modal numinput events */ - if (handleNumInput(&(t->num), event)) { - t->redraw |= TREDRAW_HARD; + /* Modal numinput events */ + if (!handled && handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } } } /* else do non-mapped events */ else if (event->val == KM_PRESS) { - switch (event->type) { - case RIGHTMOUSE: - t->state = TRANS_CANCEL; - break; - /* enforce redraw of transform when modifiers are used */ - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - t->modifiers |= MOD_CONSTRAINT_PLANE; - t->redraw |= TREDRAW_HARD; - break; + /* Handle modal numinput events first, if already activated. */ + if (hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } + else { + switch (event->type) { + case RIGHTMOUSE: + t->state = TRANS_CANCEL; + handled = true; + break; + /* enforce redraw of transform when modifiers are used */ + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + t->modifiers |= MOD_CONSTRAINT_PLANE; + t->redraw |= TREDRAW_HARD; + handled = true; + break; - case SPACEKEY: - t->state = TRANS_CONFIRM; - break; + case SPACEKEY: + t->state = TRANS_CONFIRM; + handled = true; + break; - case MIDDLEMOUSE: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - /* exception for switching to dolly, or trackball, in camera view */ - if (t->flag & T_CAMERA) { - if (t->mode == TFM_TRANSLATION) - setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); - else if (t->mode == TFM_ROTATION) { - restoreTransObjects(t); - initTrackball(t); - } - } - else { - t->modifiers |= MOD_CONSTRAINT_SELECT; - if (t->con.mode & CON_APPLY) { - stopConstraint(t); + case MIDDLEMOUSE: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + /* exception for switching to dolly, or trackball, in camera view */ + if (t->flag & T_CAMERA) { + if (t->mode == TFM_TRANSLATION) + setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); + else if (t->mode == TFM_ROTATION) { + restoreTransObjects(t); + initTrackball(t); + } } else { - if (event->shift) { - initSelectConstraint(t, t->spacemtx); + t->modifiers |= MOD_CONSTRAINT_SELECT; + if (t->con.mode & CON_APPLY) { + stopConstraint(t); } else { - /* bit hackish... but it prevents mmb select to print the orientation from menu */ - strcpy(t->spacename, "global"); - initSelectConstraint(t, mati); + if (event->shift) { + initSelectConstraint(t, t->spacemtx); + } + else { + /* bit hackish... but it prevents mmb select to print the orientation from menu */ + strcpy(t->spacename, "global"); + initSelectConstraint(t, mati); + } + postSelectConstraint(t); } - postSelectConstraint(t); } + t->redraw |= TREDRAW_HARD; + handled = true; } - t->redraw |= TREDRAW_HARD; - } - break; - case ESCKEY: - t->state = TRANS_CANCEL; - break; - case PADENTER: - case RETKEY: - t->state = TRANS_CONFIRM; - break; - case GKEY: - /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { - resetTransModal(t); - resetTransRestrictions(t); - restoreTransObjects(t); - initTranslation(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - } - break; - case SKEY: - /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { - resetTransModal(t); - resetTransRestrictions(t); - restoreTransObjects(t); - initResize(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - } - break; - case RKEY: - /* only switch when... */ - if (!(t->options & CTX_TEXTURE)) { - if (ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + break; + case ESCKEY: + t->state = TRANS_CANCEL; + handled = true; + break; + case PADENTER: + case RETKEY: + t->state = TRANS_CONFIRM; + handled = true; + break; + case GKEY: + /* only switch when... */ + if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { resetTransModal(t); resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case SKEY: + /* only switch when... */ + if (ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { + resetTransModal(t); + resetTransRestrictions(t); + restoreTransObjects(t); + initResize(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case RKEY: + /* only switch when... */ + if (!(t->options & CTX_TEXTURE)) { + if (ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + resetTransModal(t); + resetTransRestrictions(t); - if (t->mode == TFM_ROTATION) { - restoreTransObjects(t); - initTrackball(t); - } - else { - restoreTransObjects(t); - initRotation(t); + if (t->mode == TFM_ROTATION) { + restoreTransObjects(t); + initTrackball(t); + } + else { + restoreTransObjects(t); + initRotation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; } - initSnapping(t, NULL); // need to reinit after mode change + } + break; + case CKEY: + if (event->alt) { + t->flag ^= T_PROP_CONNECTED; + sort_trans_data_dist(t); + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + else { + stopConstraint(t); t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case XKEY: + case YKEY: + case ZKEY: + transform_event_xyz_constraint(t, event->type, cmode); + handled = true; + break; + case OKEY: + if (t->flag & T_PROP_EDIT && event->shift) { + t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case PADPLUSKEY: + if (event->alt && t->flag & T_PROP_EDIT) { + t->prop_size *= 1.1f; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + break; + case PAGEUPKEY: + case WHEELDOWNMOUSE: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, 1); + } + else { + view_editmove(event->type); } - } - break; - case CKEY: - if (event->alt) { - t->flag ^= T_PROP_CONNECTED; - sort_trans_data_dist(t); - calculatePropRatio(t); t->redraw = TREDRAW_HARD; - } - else { - stopConstraint(t); - t->redraw |= TREDRAW_HARD; - } - break; - case XKEY: - case YKEY: - case ZKEY: - transform_event_xyz_constraint(t, event->type, cmode); - break; - case OKEY: - if (t->flag & T_PROP_EDIT && event->shift) { - t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; - calculatePropRatio(t); - t->redraw |= TREDRAW_HARD; - } - break; - case PADPLUSKEY: - if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size *= 1.1f; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); - calculatePropRatio(t); - } - t->redraw = TREDRAW_HARD; - break; - case PAGEUPKEY: - case WHEELDOWNMOUSE: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, 1); - } - else { - view_editmove(event->type); - } - t->redraw = TREDRAW_HARD; - break; - case PADMINUS: - if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size *= 0.90909090f; - calculatePropRatio(t); - } - t->redraw = TREDRAW_HARD; - break; - case PAGEDOWNKEY: - case WHEELUPMOUSE: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, -1); - } - else { - view_editmove(event->type); - } - t->redraw = TREDRAW_HARD; - break; - case LEFTALTKEY: - case RIGHTALTKEY: - if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { - t->flag |= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - } - - break; - default: - handled = 0; - break; - } + handled = true; + break; + case PADMINUS: + if (event->alt && t->flag & T_PROP_EDIT) { + t->prop_size *= 0.90909090f; + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + break; + case PAGEDOWNKEY: + case WHEELUPMOUSE: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, -1); + } + else { + view_editmove(event->type); + } + t->redraw = TREDRAW_HARD; + handled = true; + break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { + t->flag |= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + default: + break; + } - /* Numerical input events */ - if (handleNumInput(&(t->num), event)) { - t->redraw |= TREDRAW_HARD; + /* Numerical input events */ + if (!handled && handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } } /* Snapping key events */ t->redraw |= handleSnapping(t, event); - } else if (event->val == KM_RELEASE) { switch (event->type) { @@ -1412,6 +1469,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) case RIGHTSHIFTKEY: t->modifiers &= ~MOD_CONSTRAINT_PLANE; t->redraw |= TREDRAW_HARD; + handled = true; break; case MIDDLEMOUSE: @@ -1419,6 +1477,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->modifiers &= ~MOD_CONSTRAINT_SELECT; postSelectConstraint(t); t->redraw |= TREDRAW_HARD; + handled = true; } break; case LEFTALTKEY: @@ -1426,11 +1485,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag &= ~T_ALT_TRANSFORM; t->redraw |= TREDRAW_HARD; + handled = true; } - break; default: - handled = 0; break; } @@ -1442,8 +1500,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) } } } - else - handled = 0; // Per transform event, if present if (t->handleEvent) @@ -2706,8 +2762,12 @@ static void initBend(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = DEG2RAD(5.0); t->snap[2] = DEG2RAD(1.0); - - t->num.increment = 1.0f; + + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + t->num.unit_type[1] = B_UNIT_LENGTH; t->flag |= T_NO_CONSTRAINT; @@ -2795,7 +2855,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) &c[0], &c[NUM_STR_REP_LEN], WM_bool_as_string(is_clamp)); - values.angle = DEG2RADF(values.angle); values.scale = values.scale / data->warp_init_dist; } else { @@ -2896,8 +2955,10 @@ static void initShear(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - - t->num.increment = 0.1f; + + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */ t->flag |= T_NO_CONSTRAINT; } @@ -3028,11 +3089,15 @@ static void initResize(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); t->flag |= T_NULL_ONE; - t->num.flag |= NUM_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; if (!t->obedit) { t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[1] |= NUM_NO_ZERO; + t->num.val_flag[2] |= NUM_NO_ZERO; } t->idx_max = 2; @@ -3041,7 +3106,11 @@ static void initResize(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]) @@ -3313,11 +3382,15 @@ static void initSkinResize(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); t->flag |= T_NULL_ONE; - t->num.flag |= NUM_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; if (!t->obedit) { t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[1] |= NUM_NO_ZERO; + t->num.val_flag[2] |= NUM_NO_ZERO; } t->idx_max = 2; @@ -3326,7 +3399,11 @@ static void initSkinResize(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) @@ -3415,9 +3492,11 @@ static void initToSphere(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE; + t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE; t->flag |= T_NO_CONSTRAINT; // Calculate average radius @@ -3517,7 +3596,10 @@ static void initRotation(TransInfo *t) t->snap[1] = DEG2RAD(5.0); t->snap[2] = DEG2RAD(1.0); - t->num.increment = 1.0f; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; if (t->flag & T_2D_EDIT) t->flag |= T_NO_CONSTRAINT; @@ -3808,8 +3890,8 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); - /* Clamp between -180 and 180 */ - final = angle_wrap_rad(DEG2RADF(final)); + /* Clamp between -PI and PI */ + final = angle_wrap_rad(final); } else { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %.2f%s %s"), @@ -3850,7 +3932,11 @@ static void initTrackball(TransInfo *t) t->snap[1] = DEG2RAD(5.0); t->snap[2] = DEG2RAD(1.0); - t->num.increment = 1.0f; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + t->num.unit_type[1] = B_UNIT_ROTATION; t->flag |= T_NO_CONSTRAINT; } @@ -3911,9 +3997,6 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"), &c[0], &c[NUM_STR_REP_LEN], t->proptext); - - phi[0] = DEG2RADF(phi[0]); - phi[1] = DEG2RADF(phi[1]); } else { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %.2f %.2f %s"), @@ -3987,7 +4070,12 @@ static void initTranslation(TransInfo *t) t->snap[1] = t->snap[2] = 1.0f; } - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_LENGTH; + t->num.unit_type[1] = B_UNIT_LENGTH; + t->num.unit_type[2] = B_UNIT_LENGTH; + } static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]) @@ -4215,7 +4303,9 @@ static void initShrinkFatten(TransInfo *t) t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_LENGTH; t->flag |= T_NO_CONSTRAINT; } @@ -4309,7 +4399,10 @@ static void initTilt(TransInfo *t) t->snap[1] = DEG2RAD(5.0); t->snap[2] = DEG2RAD(1.0); - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -4336,8 +4429,6 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); - final = DEG2RADF(final); - /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */ t->values[0] = final; } @@ -4383,10 +4474,12 @@ static void initCurveShrinkFatten(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; t->flag |= T_NO_CONSTRAINT; } @@ -4456,10 +4549,12 @@ static void initMaskShrinkFatten(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; t->flag |= T_NO_CONSTRAINT; } @@ -4550,7 +4645,9 @@ static void initPushPull(TransInfo *t) t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_LENGTH; } @@ -4639,7 +4736,9 @@ static void initBevelWeight(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -4716,7 +4815,9 @@ static void initCrease(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -4792,13 +4893,19 @@ static void initBoneSize(TransInfo *t) t->idx_max = 2; t->num.idx_max = 2; - t->num.flag |= NUM_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]) @@ -4919,7 +5026,9 @@ static void initBoneEnvelope(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -5864,7 +5973,9 @@ static void initEdgeSlide(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -6370,7 +6481,9 @@ static void initVertSlide(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -6626,7 +6739,10 @@ static void initBoneRoll(TransInfo *t) t->snap[1] = DEG2RAD(5.0); t->snap[2] = DEG2RAD(1.0); - t->num.increment = 1.0f; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } @@ -6651,8 +6767,6 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]); - - final = DEG2RADF(final); } else { BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %.2f"), RAD2DEGF(final)); @@ -6693,7 +6807,9 @@ static void initBakeTime(TransInfo *t) t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */ } static void applyBakeTime(TransInfo *t, const int mval[2]) @@ -6920,7 +7036,11 @@ static void initSeqSlide(TransInfo *t) t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base); t->snap[2] = 10.0f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* Would be nice to have a time handling in units as well (supporting frames in addition to "natural" time...). */ + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; } static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN]) @@ -7187,7 +7307,10 @@ static void initTimeTranslate(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* No time unit supporting frames currently... */ + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) @@ -7346,7 +7469,10 @@ static void initTimeSlide(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* No time unit supporting frames currently... */ + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN]) @@ -7481,7 +7607,7 @@ static void initTimeScale(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); t->flag |= T_NULL_ONE; - t->num.flag |= NUM_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; /* num-input has max of (n-1) */ t->idx_max = 0; @@ -7492,7 +7618,9 @@ static void initTimeScale(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; - t->num.increment = t->snap[1]; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeScale(TransInfo *t, char str[MAX_INFO_LEN]) diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 6c0bf92a484..89d1bc7acdf 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -98,4 +98,9 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_PYTHON) + add_definitions(-DWITH_PYTHON) + set(INC ${INC} ../../python) +endif() + blender_add_lib(bf_editor_util "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript index 223ee5731f1..0876fe48c91 100644 --- a/source/blender/editors/util/SConscript +++ b/source/blender/editors/util/SConscript @@ -46,4 +46,8 @@ incs = [ if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if env['WITH_BF_PYTHON']: + defs.append('WITH_PYTHON') + incs.append('../../python') + env.BlenderLib ( 'bf_editors_util', sources, incs, defines=defs, libtype=['core','player'], priority=[330,210] ) diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 0feaf936172..891051185ac 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -24,93 +24,97 @@ * \ingroup edutil */ - -#include <math.h> /* fabs */ -#include <stdio.h> /* for size_t */ +#include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_string_cursor_utf8.h" + +#include "BKE_context.h" +#include "BKE_unit.h" + +#include "DNA_scene_types.h" +#include "WM_api.h" #include "WM_types.h" +#ifdef WITH_PYTHON +#include "BPY_extern.h" +#endif + #include "ED_numinput.h" + +/* NumInput.val_flag[] */ +enum { + /* (1 << 8) and below are reserved for public flags! */ + NUM_EDITED = (1 << 9), /* User has edited this value somehow. */ + NUM_INVALID = (1 << 10), /* Current expression for this value is invalid. */ +}; + /* ************************** 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; + n->unit_sys = USER_UNIT_NONE; + n->unit_type[0] = n->unit_type[1] = n->unit_type[2] = B_UNIT_NONE; + n->idx = 0; + n->idx_max = 0; + n->flag = 0; + n->val_flag[0] = n->val_flag[1] = n->val_flag[2] = 0; + zero_v3(n->val_org); + zero_v3(n->val); + n->str[0] = '\0'; + n->str_cur = 0; + copy_v3_fl(n->val_inc, 1.0f); } +/* str must be NUM_STR_REP_LEN * (idx_max + 1) length. */ void outputNumInput(NumInput *n, char *str) { - char cur; - char inv[] = "1/"; short i, j; const int ln = NUM_STR_REP_LEN; + const int prec = 4; /* draw-only, and avoids too much issues with radian->degrees conversion. */ 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); - break; + i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j; + + if (n->val_flag[i] & NUM_EDITED) { + if (i == n->idx && n->str[0]) { + char before_cursor[NUM_STR_REP_LEN]; + char val[16]; + if (n->val_flag[i] & NUM_INVALID) { + BLI_strncpy(val, "Invalid", sizeof(val)); + } + else { + bUnit_AsString(val, sizeof(val), (double)n->val[i], prec, + n->unit_sys, n->unit_type[i], true, false); + } + BLI_strncpy(before_cursor, n->str, n->str_cur + 1); /* +1 because of trailing '\0' */ + BLI_snprintf(&str[j * ln], ln, "[%s|%s] = %s", before_cursor, &n->str[n->str_cur], val); } + else { + const char *cur = (i == n->idx) ? "|" : ""; + if (n->unit_use_radians && n->unit_type[i] == B_UNIT_ROTATION) { + /* Radian exception... */ + BLI_snprintf(&str[j * ln], ln, "%s%.6gr%s", cur, n->val[i], cur); + } + else { + char tstr[NUM_STR_REP_LEN]; + bUnit_AsString(tstr, ln, (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false); + BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur); + } + } + } + else { + const char *cur = (i == n->idx) ? "|" : ""; + BLI_snprintf(&str[j * ln], ln, "%sNONE%s", cur, cur); + } } } @@ -119,8 +123,9 @@ bool hasNumInput(const NumInput *n) short i; for (i = 0; i <= n->idx_max; i++) { - if (n->ctrl[i]) + if (n->val_flag[i] & NUM_EDITED) { return true; + } } return false; @@ -132,177 +137,247 @@ bool hasNumInput(const NumInput *n) void applyNumInput(NumInput *n, float *vec) { short i, j; + float val; 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; + i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j; + val = (!(n->val_flag[i] & NUM_EDITED) && n->val_flag[i] & NUM_NULL_ONE) ? 1.0f : n->val[i]; - if (n->ctrl[i] == 0 && n->flag & NUM_NULL_ONE) { - vec[j] = 1.0f; + if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) { + val = 0.0f; } - else if (n->val[i] == 0.0f && n->flag & NUM_NO_ZERO) { - vec[j] = 0.0001f; + if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) { + val = 0.0001f; } - else { - if (n->inv[i]) { - vec[j] = 1.0f / n->val[i]; - } - else { - vec[j] = n->val[i]; + if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) { + val = floorf(val + 0.5f); + if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) { + val = 1.0f; } } + vec[j] = val; } } } -bool handleNumInput(NumInput *n, const wmEvent *event) + +static void value_to_editstr(NumInput *n, int idx) { - float Val = 0; - short idx = n->idx, idx_max = n->idx_max; + const int prec = 6; /* editing, higher precision needed. */ + bUnit_AsString(n->str, NUM_STR_REP_LEN, (double)n->val[idx], prec, + n->unit_sys, n->unit_type[idx], true, false); + n->str_cur = strlen(n->str); +} - if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case NUM_MODAL_INCREMENT_UP: - if (!n->ctrl[idx]) - n->ctrl[idx] = 1; +static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len) +{ + int cur = n->str_cur; + int len = strlen(&n->str[cur]) + 1; /* +1 for the trailing '\0'. */ + int n_cur = cur + buf_len; - n->val[idx] += n->increment; - break; - case NUM_MODAL_INCREMENT_DOWN: - if (!n->ctrl[idx]) - n->ctrl[idx] = 1; + if (n_cur + len >= NUM_STR_REP_LEN) { + return false; + } + + memmove(&n->str[n_cur], &n->str[cur], len); + memcpy(&n->str[cur], buf, sizeof(char) * buf_len); + + n->str_cur = n_cur; + return true; +} + +bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) +{ + const char *utf8_buf = NULL; + char ascii[2] = {'\0', '\0'}; + bool updated = false; + short idx = n->idx, idx_max = n->idx_max; + short dir = STRCUR_DIR_NEXT, mode = STRCUR_JUMP_NONE; + int cur; + double val; - n->val[idx] -= n->increment; + switch (event->type) { + case EVT_MODAL_MAP: + if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) { + n->val[idx] += (event->val == NUM_MODAL_INCREMENT_UP) ? n->val_inc[idx] : -n->val_inc[idx]; + value_to_editstr(n, idx); + n->val_flag[idx] |= NUM_EDITED; + updated = true; + } + else { + /* might be a char too... */ + utf8_buf = event->utf8_buf; + ascii[0] = event->ascii; + } + break; + case BACKSPACEKEY: + /* Part specific to backspace... */ + if (!(n->val_flag[idx] & NUM_EDITED)) { + copy_v3_v3(n->val, n->val_org); + n->val_flag[0] &= ~NUM_EDITED; + n->val_flag[1] &= ~NUM_EDITED; + n->val_flag[2] &= ~NUM_EDITED; + updated = true; 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; - } + } + else if (event->shift || !n->str[0]) { + n->val[idx] = n->val_org[idx]; + n->val_flag[idx] &= ~NUM_EDITED; + n->str[0] = '\0'; + n->str_cur = 0; + updated = true; 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; + } + /* Else, common behavior with DELKEY, only difference is remove char(s) before/after the cursor. */ + dir = STRCUR_DIR_PREV; + /* fall-through */ + case DELKEY: + if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) { + int t_cur = cur = n->str_cur; + if (event->ctrl) { + mode = STRCUR_JUMP_DELIM; } - break; - case PADMINUS: - if (event->alt) - break; - /* fall-through */ - case MINUSKEY: - if (n->flag & NUM_NO_NEGATIVE) - return 0; - - if (n->ctrl[idx]) { - n->ctrl[idx] *= -1; - n->val[idx] *= -1; + BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true); + if (t_cur != cur) { + if (t_cur < cur) { + SWAP(int, t_cur, cur); + n->str_cur = cur; + } + memmove(&n->str[cur], &n->str[t_cur], strlen(&n->str[t_cur]) + 1); /* +1 for trailing '\0'. */ + updated = true; } - else - n->ctrl[idx] = -1; - break; - case PADSLASHKEY: case SLASHKEY: - if (n->flag & NUM_NO_FRACTION) - return 0; + } + else { + return false; + } + break; + case LEFTARROWKEY: + dir = STRCUR_DIR_PREV; + /* fall-through */ + case RIGHTARROWKEY: + cur = n->str_cur; + if (event->ctrl) { + mode = STRCUR_JUMP_DELIM; + } + BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true); + if (cur != n->str_cur) { + n->str_cur = cur; + return true; + } + return false; + case HOMEKEY: + if (n->str[0]) { + n->str_cur = 0; + return true; + } + return false; + case ENDKEY: + if (n->str[0]) { + n->str_cur = strlen(n->str); + return true; + } + return false; + case TABKEY: + n->val_org[idx] = n->val[idx]; - 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; + idx += event->ctrl ? -1 : 1; + idx %= idx_max + 1; + n->idx = idx; + n->val[idx] = n->val_org[idx]; + if (n->val_flag[idx] & NUM_EDITED) { + value_to_editstr(n, idx); + } + else { + n->str[0] = '\0'; + n->str_cur = 0; + } + return true; + case CKEY: + if (event->ctrl) { + /* Copy current str to the copypaste buffer. */ + WM_clipboard_text_set(n->str, 0); + updated = true; break; - case PAD9: case NINEKEY: - Val += 1.0f; - /* fall-through */ - case PAD8: case EIGHTKEY: - Val += 1.0f; - /* fall-through */ - case PAD7: case SEVENKEY: - Val += 1.0f; - /* fall-through */ - case PAD6: case SIXKEY: - Val += 1.0f; - /* fall-through */ - case PAD5: case FIVEKEY: - Val += 1.0f; - /* fall-through */ - case PAD4: case FOURKEY: - Val += 1.0f; - /* fall-through */ - case PAD3: case THREEKEY: - Val += 1.0f; - /* fall-through */ - case PAD2: case TWOKEY: - Val += 1.0f; - /* fall-through */ - case PAD1: case ONEKEY: - Val += 1.0f; - /* fall-through */ - 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; + } + /* fall-through */ + case VKEY: + if (event->ctrl) { + /* extract the first line from the clipboard */ + char *pbuf = WM_clipboard_text_get(0); + + if (pbuf) { + bool success; + /* Only copy string until first of this char. */ + char *cr = strchr(pbuf, '\r'); + char *cn = strchr(pbuf, '\n'); + if (cn && cn < cr) cr = cn; + if (cr) *cr = '\0'; + + success = editstr_insert_at_cursor(n, pbuf, strlen(pbuf)); + + MEM_freeN(pbuf); + if (!success) { + return false; } + + n->val_flag[idx] |= NUM_EDITED; } + updated = true; break; - default: - return 0; + } + /* fall-through */ + default: + utf8_buf = event->utf8_buf; + ascii[0] = event->ascii; + break; + } + + if (utf8_buf && !utf8_buf[0] && ascii[0]) { + /* Fallback to ascii. */ + utf8_buf = ascii; + } + + if (utf8_buf && utf8_buf[0]) { + if (!editstr_insert_at_cursor(n, utf8_buf, BLI_str_utf8_size(utf8_buf))) { + return false; + } + + n->val_flag[idx] |= NUM_EDITED; + } + else if (!updated) { + return false; + } + + /* At this point, our value has changed, try to interpret it with python (if str is not empty!). */ + if (n->str[0]) { +#ifdef WITH_PYTHON + char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */ + const char *default_unit = NULL; + + /* Make radian default unit when needed. */ + if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) + default_unit = "r"; + + BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert)); + + bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, 1.0, + n->unit_sys, n->unit_type[idx]); + + /* Note: with angles, we always get values as radians here... */ + if (BPY_button_exec(C, str_unit_convert, &val, false) != -1) { + n->val[idx] = (float)val; + n->val_flag[idx] &= ~NUM_INVALID; + } + else { + n->val_flag[idx] |= NUM_INVALID; } +#else /* Very unlikely, but does not harm... */ + n->val[idx] = (float)atof(n->str); +#endif /* WITH_PYTHON */ } - - // printf("%f\n", n->val[idx]); /* REDRAW SINCE NUMBERS HAVE CHANGED */ - return 1; + return true; } |