Fix T41590: When scene scale is not 1.0, and units are "None," Blender assumes translations are in meters.

Turned out there were several issues in handling of scale parameter by numinput.
Fixed that by factorizing more some code in common with 'usual' numbuttons eval code
(new `bUnit_getScaleUnit()` helper will return valid scaled value, depending on
given system and type).

Now, numinput behaves as expected - using default unit amended by scale in case no unit is given
(i.e. entering '20' with a scale of 0.01 will give you 20cm, and '20cm' as well!).
This commit is contained in:
Bastien Montagne 2014-08-26 12:04:24 +02:00
parent 600248783b
commit 0e3fa0b761
Notes: blender-bot 2023-02-14 10:09:32 +01:00
Referenced by issue #41590, When scene scale is not 1.0, and units are "None," Blender assumes translations are in meters
10 changed files with 73 additions and 55 deletions

View File

@ -31,6 +31,8 @@
extern "C" {
#endif
struct UnitSettings;
/* 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) */
@ -39,6 +41,11 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int syste
/* replace units with values, used before python button evaluation */
bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type);
/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
* and unit->scale_length.
*/
double bUnit_getScaleUnit(struct UnitSettings *unit, const int unit_type, double value);
/* make string keyboard-friendly: 10µm --> 10um */
void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int system, int type);

View File

@ -37,6 +37,8 @@
#include "BKE_unit.h" /* own include */
#include "DNA_scene_types.h"
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
@ -789,6 +791,29 @@ double bUnit_BaseScalar(int system, int type)
return unit_default(usys)->scalar;
}
double bUnit_getScaleUnit(UnitSettings *unit, const int unit_type, double value)
{
if (unit->system == USER_UNIT_NONE) {
/* Never apply scale_length when not using a unit setting! */
return value;
}
switch (unit_type) {
case B_UNIT_LENGTH:
return value * (double)unit->scale_length;
case B_UNIT_CAMERA:
return value * (double)unit->scale_length;
case B_UNIT_AREA:
return value * pow(unit->scale_length, 2);
case B_UNIT_VOLUME:
return value * pow(unit->scale_length, 3);
case B_UNIT_MASS:
return value * pow(unit->scale_length, 3);
default:
return value;
}
}
/* external access */
bool bUnit_IsValid(int system, int type)
{

View File

@ -637,7 +637,7 @@ static void ed_marker_move_update_header(bContext *C, wmOperator *op)
}
if (hasNumInput(&mm->num)) {
outputNumInput(&mm->num, str_offs, scene->unit.scale_length);
outputNumInput(&mm->num, str_offs, &scene->unit);
}
else if (use_time) {
BLI_snprintf(str_offs, sizeof(str_offs), "%.2f", FRA2TIME(offs));

View File

@ -64,6 +64,8 @@ enum {
/* (1 << 9) and above are reserved for internal flags! */
};
struct UnitSettings;
/*********************** NumInput ********************************/
/* There are important things to note here for code using numinput:
@ -76,7 +78,7 @@ enum {
*/
void initNumInput(NumInput *n);
void outputNumInput(NumInput *n, char *str, const float scale_length);
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings);
bool hasNumInput(const NumInput *n);
bool applyNumInput(NumInput *n, float *vec);
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event);

View File

@ -1942,27 +1942,13 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
UnitSettings *unit = but->block->unit;
int unit_type = uiButGetUnitType(but);
if (unit_type == PROP_UNIT_LENGTH) {
return value * (double)unit->scale_length;
}
else if (unit_type == PROP_UNIT_CAMERA) {
return value * (double)unit->scale_length;
}
else if (unit_type == PROP_UNIT_AREA) {
return value * pow(unit->scale_length, 2);
}
else if (unit_type == PROP_UNIT_VOLUME) {
return value * pow(unit->scale_length, 3);
}
else if (unit_type == PROP_UNIT_MASS) {
return value * pow(unit->scale_length, 3);
}
else if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
/* Time unit is a bit special, not handled by bUnit_getScaleUnit() for now. */
if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
Scene *scene = CTX_data_scene(but->block->evil_C);
return FRA2TIME(value);
}
else {
return value;
return bUnit_getScaleUnit(unit, RNA_SUBTYPE_UNIT_VALUE(unit_type), value);
}
}

View File

@ -88,7 +88,7 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type");
if (hasNumInput(&opdata->num_input)) {
outputNumInput(&opdata->num_input, offset_str, sce->unit.scale_length);
outputNumInput(&opdata->num_input, offset_str, &sce->unit);
}
else {
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));

View File

@ -90,7 +90,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
if (sa) {
char flts_str[NUM_STR_REP_LEN * 2];
if (hasNumInput(&opdata->num_input))
outputNumInput(&opdata->num_input, flts_str, sce->unit.scale_length);
outputNumInput(&opdata->num_input, flts_str, &sce->unit);
else {
BLI_snprintf(flts_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "thickness"));
BLI_snprintf(flts_str + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "depth"));

View File

@ -686,7 +686,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
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, sce->unit.scale_length);
outputNumInput(&lcd->num, str_rep, &sce->unit);
}
else {
BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", cuts);

View File

@ -2872,7 +2872,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
&c[0], &c[NUM_STR_REP_LEN],
@ -3040,7 +3040,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext);
}
@ -3141,7 +3141,7 @@ static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
@ -3555,7 +3555,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext);
}
@ -3919,7 +3919,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
}
@ -4023,7 +4023,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"),
&c[0], &c[NUM_STR_REP_LEN], t->proptext);
@ -4125,7 +4125,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]
float dist;
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
dist = len_v3(t->num.val);
}
else {
@ -4373,7 +4373,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c);
}
else {
@ -4468,7 +4468,7 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
@ -4546,7 +4546,7 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c);
}
else {
@ -4624,7 +4624,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c);
}
else {
@ -4717,7 +4717,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
}
@ -4810,7 +4810,7 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
if (weight >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
@ -4888,7 +4888,7 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
if (crease >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext);
@ -4958,7 +4958,7 @@ static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
@ -5095,7 +5095,7 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c);
}
else {
@ -6270,7 +6270,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
if (is_proportional) {
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"),
@ -6793,7 +6793,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs);
}
else {
@ -6860,7 +6860,7 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]);
}
@ -6934,7 +6934,7 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, t->scene->unit.scale_length);
outputNumInput(&(t->num), c, &t->scene->unit);
if (time >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext);
@ -7145,7 +7145,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
size_t ofs = 0;
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
@ -7371,7 +7371,7 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
/* if numeric input is active, use results from that, otherwise apply snapping to result */
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
const Scene *scene = t->scene;
@ -7535,7 +7535,7 @@ static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
float minx = *((float *)(t->customData));
@ -7683,7 +7683,7 @@ static void headerTimeScale(TransInfo *t, char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num))
outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
outputNumInput(&(t->num), tvec, &t->scene->unit);
else
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);

View File

@ -87,7 +87,7 @@ void initNumInput(NumInput *n)
}
/* str must be NUM_STR_REP_LEN * (idx_max + 1) length. */
void outputNumInput(NumInput *n, char *str, const float scale_length)
void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
{
short j;
const int ln = NUM_STR_REP_LEN;
@ -98,7 +98,7 @@ void outputNumInput(NumInput *n, char *str, const float scale_length)
const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
/* Use scale_length if needed! */
const float fac = ELEM(n->unit_type[j], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME) ? scale_length : 1.0f;
const float fac = (float)bUnit_getScaleUnit(unit_settings, n->unit_type[j], 1.0);
if (n->val_flag[i] & NUM_EDITED) {
/* Get the best precision, allows us to draw '10.0001' as '10' instead! */
@ -478,26 +478,24 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
#ifdef WITH_PYTHON
Scene *sce = CTX_data_scene(C);
double val;
float fac = 1.0f;
char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */
const char *default_unit = NULL;
/* Use scale_length if needed! */
const float fac = (float)bUnit_getScaleUnit(&sce->unit, n->unit_type[idx], 1.0);
/* Make radian default unit when needed. */
if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION)
default_unit = "r";
/* Use scale_length if needed! */
if (ELEM(n->unit_type[idx], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME))
fac /= sce->unit.scale_length;
BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert));
bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, 1.0,
bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, fac,
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 * fac;
n->val[idx] = (float)val;
n->val_flag[idx] &= ~NUM_INVALID;
}
else {