Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2013-12-21 20:11:43 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2013-12-21 20:44:48 +0400
commit87cc890aef53c4660448b1125dc0c40a187ae1f2 (patch)
tree5742d07986fa362b4f17590129dd8c5692cd51b7
parentf72b86da8cab4bff482fc58095d14c97823fa39f (diff)
Support units in modal numinput
Summary: This completly changes the way modal numinput is handled. Now, edited expression is a string, which then gets unit- and py-evaluated to get a float value. We gain many power and flexibility, but lose a few "shortcuts" like '-' to negate, or '/' to inverse (if they are really needed, we still can add them with modifiers, like e.g. ctrl-/ or so). Features: - units (cm, ", deg, etc.). - basic operations from python/BKE_unit (+, *, **, etc.), and math constants and functions (pi, sin, etc.). - you can navigate in edited value (left/right key, ctrl to move by block) and insert/delete chars, e.g. to fix a typo without having to rewrite everything. - you can go to next/previous value with (ctrl-)TAB key. - As before, hitting backspace after having deleted all leading chars will first reset the edited value to init state, and on second press, the whole "modal numinput" editing will be cancelled, going back to usual transform with mouse. Notes: - Did not touch to how values are shown in header when modal numinput is not enabled (would do that in another commit), so this is still quite inconsistent. - Added back radian support in BKE_unit. - Added arcminute/arcsecond to BKE_unit. (those unit changes affect all angle UI controls, btw, so you can now enter radians or longitude/latitude values when in degrees units). Related to T37600. Reviewers: brecht, campbellbarton, carter2422 Reviewed By: brecht, campbellbarton, carter2422 Thanks everybody! Differential Revision: http://developer.blender.org/D61
-rw-r--r--source/blender/blenkernel/BKE_unit.h2
-rw-r--r--source/blender/blenkernel/intern/unit.c43
-rw-r--r--source/blender/editors/animation/anim_markers.c10
-rw-r--r--source/blender/editors/include/ED_numinput.h55
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c123
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c255
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c249
-rw-r--r--source/blender/editors/transform/transform.c974
-rw-r--r--source/blender/editors/util/CMakeLists.txt5
-rw-r--r--source/blender/editors/util/SConscript4
-rw-r--r--source/blender/editors/util/numinput.c489
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;
}