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
path: root/source
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2018-10-03 11:20:16 +0300
committerJacques Lucke <mail@jlucke.com>2018-10-03 11:20:16 +0300
commit2d21eb79ad48485bc7b3385d6df5c2c25fd88ee0 (patch)
tree57d18e1020c8acc2d46110bd43c0721dc30b7d76 /source
parent1c3411ac899d1ae8dfd790249a53054698bdd1e8 (diff)
Units: Support for fixed units
Users can select the main unit they want to use now. Previously the displayed unit always depended on the magnitude of the value. The old behavior can be restored by switching to the "Adaptive" mode for length, mass and time units. Meters, kilograms and seconds are the default units for new and old scenes. The selected unit is also the default unit for user input. E.g. if cm is selected, whenever the user inputs a unitless number into a field of type length, it will be interpreted as cm. Reviewer: brecht Differential: https://developer.blender.org/D3740
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_unit.h13
-rw-r--r--source/blender/blenkernel/intern/scene.c3
-rw-r--r--source/blender/blenkernel/intern/unit.c224
-rw-r--r--source/blender/blenloader/intern/versioning_280.c12
-rw-r--r--source/blender/draw/modes/edit_mesh_mode_text.c11
-rw-r--r--source/blender/editors/include/ED_numinput.h2
-rw-r--r--source/blender/editors/interface/interface.c26
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c13
-rw-r--r--source/blender/editors/transform/transform.c12
-rw-r--r--source/blender/editors/util/numinput.c54
-rw-r--r--source/blender/makesdna/DNA_scene_types.h7
-rw-r--r--source/blender/makesrna/intern/rna_scene.c89
14 files changed, 360 insertions, 129 deletions
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
index 82a4659eec7..bb7fb006038 100644
--- a/source/blender/blenkernel/BKE_unit.h
+++ b/source/blender/blenkernel/BKE_unit.h
@@ -31,14 +31,23 @@
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) */
-size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad);
+size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad);
+size_t bUnit_AsString2(char *str, int len_max, double value, int prec, int type, const struct UnitSettings *settings, bool pad);
/* 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);
+/* return true if the string contains any valid unit for the given type */
+bool bUnit_ContainsUnit(const char *str, int system, int type);
+
+/* if user does not specify a unit, multiply with this value */
+double bUnit_PreferredUnitScalar(const struct UnitSettings *settings, int type);
+
/* make string keyboard-friendly: 10µm --> 10um */
void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int system, int type);
@@ -56,9 +65,11 @@ bool bUnit_IsValid(int system, int type);
void bUnit_GetSystem(int system, int type, void const **r_usys_pt, int *r_len);
int bUnit_GetBaseUnit(const void *usys_pt);
+int bUnit_GetBaseUnitOfType(int system, int type);
const char *bUnit_GetName(const void *usys_pt, int index);
const char *bUnit_GetNameDisplay(const void *usys_pt, int index);
double bUnit_GetScaler(const void *usys_pt, int index);
+bool bUnit_IsSuppressed(const void *usys_pt, int index);
/* aligned with PropertyUnit */
enum {
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 8c2f226eb8b..44406714771 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -703,6 +703,9 @@ void BKE_scene_init(Scene *sce)
sce->unit.system = USER_UNIT_METRIC;
sce->unit.scale_length = 1.0f;
+ sce->unit.length_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_LENGTH);
+ sce->unit.mass_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_MASS);
+ sce->unit.time_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_TIME);
pset = &sce->toolsettings->particle;
pset->flag = PE_KEEP_LENGTHS | PE_LOCK_FIRST | PE_DEFLECT_EMITTER | PE_AUTO_VELOCITY;
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 3a903eb31c1..c132053a82b 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -35,6 +35,8 @@
#include "BLI_string.h"
#include "BLI_string_utf8.h"
+#include "DNA_scene_types.h"
+
#include "BKE_unit.h" /* own include */
#ifdef WIN32
@@ -108,6 +110,8 @@ typedef struct bUnitCollection {
int length; /* to quickly find the last item */
} bUnitCollection;
+#define UNIT_COLLECTION_LENGTH(def) (sizeof(def) / sizeof(bUnitDef) - 1)
+
/* Dummy */
static struct bUnitDef buDummyDef[] = { {"", NULL, "", NULL, NULL, 1.0, 0.0}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}};
static struct bUnitCollection buDummyCollection = {buDummyDef, 0, 0, sizeof(buDummyDef)};
@@ -121,7 +125,7 @@ static const struct bUnitDef buMetricLenDef[] = {
{"decimeter", "decimeters", "dm", NULL, "10 Centimeters", UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
{"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_CM, 0.0, B_UNIT_DEF_NONE},
{"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_MM, 0.0, B_UNIT_DEF_NONE | B_UNIT_DEF_TENTH},
- {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
+ {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
/* These get displayed because of float precision problems in the transform header,
* could work around, but for now probably people wont use these */
@@ -131,7 +135,7 @@ static const struct bUnitDef buMetricLenDef[] = {
#endif
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static const struct bUnitCollection buMetricLenCollection = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef) / sizeof(bUnitDef)};
+static const struct bUnitCollection buMetricLenCollection = {buMetricLenDef, 3, 0, UNIT_COLLECTION_LENGTH(buMetricLenDef)};
static struct bUnitDef buImperialLenDef[] = {
{"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -143,7 +147,7 @@ static struct bUnitDef buImperialLenDef[] = {
{"thou", "thou", "thou", "mil", "Thou", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, /* plural for thou has no 's' */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialLenCollection = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialLenCollection = {buImperialLenDef, 4, 0, UNIT_COLLECTION_LENGTH(buImperialLenDef)};
/* Areas */
static struct bUnitDef buMetricAreaDef[] = {
@@ -157,7 +161,7 @@ static struct bUnitDef buMetricAreaDef[] = {
{"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, UNIT_COLLECTION_LENGTH(buMetricAreaDef)};
static struct bUnitDef buImperialAreaDef[] = {
{"square mile", "square miles", "sq mi", "sq m", "Square Miles", UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -169,7 +173,7 @@ static struct bUnitDef buImperialAreaDef[] = {
{"square thou", "square thous", "sq mil", NULL, "Square Thous", UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialAreaCollection = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialAreaCollection = {buImperialAreaDef, 4, 0, UNIT_COLLECTION_LENGTH(buImperialAreaDef)};
/* Volumes */
static struct bUnitDef buMetricVolDef[] = {
@@ -183,7 +187,7 @@ static struct bUnitDef buMetricVolDef[] = {
{"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM * UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricVolCollection = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricVolCollection = {buMetricVolDef, 3, 0, UNIT_COLLECTION_LENGTH(buMetricVolDef)};
static struct bUnitDef buImperialVolDef[] = {
{"cubic mile", "cubic miles", "cu mi", "cu m", "Cubic Miles", UN_SC_MI * UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -195,7 +199,7 @@ static struct bUnitDef buImperialVolDef[] = {
{"cubic thou", "cubic thous", "cu mil", NULL, "Cubic Thous", UN_SC_MIL * UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialVolCollection = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialVolCollection = {buImperialVolDef, 4, 0, UNIT_COLLECTION_LENGTH(buImperialVolDef)};
/* Mass */
static struct bUnitDef buMetricMassDef[] = {
@@ -208,7 +212,7 @@ static struct bUnitDef buMetricMassDef[] = {
{"milligram", "milligrams", "mg", NULL, "Milligrams", UN_SC_MG, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricMassCollection = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricMassCollection = {buMetricMassDef, 2, 0, UNIT_COLLECTION_LENGTH(buMetricMassDef)};
static struct bUnitDef buImperialMassDef[] = {
{"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE},
@@ -218,7 +222,7 @@ static struct bUnitDef buImperialMassDef[] = {
{"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialMassCollection = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialMassCollection = {buImperialMassDef, 3, 0, UNIT_COLLECTION_LENGTH(buImperialMassDef)};
/* Even if user scales the system to a point where km^3 is used, velocity and
* acceleration aren't scaled: that's why we have so few units for them */
@@ -229,27 +233,27 @@ static struct bUnitDef buMetricVelDef[] = {
{"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricVelCollection = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricVelCollection = {buMetricVelDef, 0, 0, UNIT_COLLECTION_LENGTH(buMetricVelDef)};
static struct bUnitDef buImperialVelDef[] = {
{"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialVelCollection = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialVelCollection = {buImperialVelDef, 0, 0, UNIT_COLLECTION_LENGTH(buImperialVelDef)};
/* Acceleration */
static struct bUnitDef buMetricAclDef[] = {
{"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricAclCollection = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricAclCollection = {buMetricAclDef, 0, 0, UNIT_COLLECTION_LENGTH(buMetricAclDef)};
static struct bUnitDef buImperialAclDef[] = {
{"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialAclCollection = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialAclCollection = {buImperialAclDef, 0, 0, UNIT_COLLECTION_LENGTH(buImperialAclDef)};
/* Time */
static struct bUnitDef buNaturalTimeDef[] = {
@@ -262,7 +266,7 @@ static struct bUnitDef buNaturalTimeDef[] = {
{"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buNaturalTimeCollection = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buNaturalTimeCollection = {buNaturalTimeDef, 3, 0, UNIT_COLLECTION_LENGTH(buNaturalTimeDef)};
static struct bUnitDef buNaturalRotDef[] = {
@@ -274,7 +278,7 @@ static struct bUnitDef buNaturalRotDef[] = {
// {"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)};
+static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, UNIT_COLLECTION_LENGTH(buNaturalRotDef)};
/* Camera Lengths */
static struct bUnitDef buCameraLenDef[] = {
@@ -285,7 +289,7 @@ static struct bUnitDef buCameraLenDef[] = {
{"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_MM, 0.0, B_UNIT_DEF_SUPPRESS},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, sizeof(buCameraLenDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, UNIT_COLLECTION_LENGTH(buCameraLenDef)};
#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1)
@@ -341,9 +345,12 @@ static const bUnitDef *unit_best_fit(
static void unit_dual_convert(
double value, const bUnitCollection *usys,
bUnitDef const **r_unit_a, bUnitDef const **r_unit_b,
- double *r_value_a, double *r_value_b)
+ double *r_value_a, double *r_value_b,
+ const bUnitDef *main_unit)
{
- const bUnitDef *unit = unit_best_fit(value, usys, NULL, 1);
+ const bUnitDef *unit;
+ if (main_unit) unit = main_unit;
+ else unit = unit_best_fit(value, usys, NULL, 1);
*r_value_a = (value < 0.0 ? ceil : floor)(value / unit->scalar) * unit->scalar;
*r_value_b = value - (*r_value_a);
@@ -426,43 +433,136 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, con
return i;
}
-/* 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, bool split, bool pad)
+static bool unit_should_be_split(int type)
{
- const bUnitCollection *usys = unit_get_system(system, type);
+ return ELEM(type, B_UNIT_LENGTH, B_UNIT_MASS, B_UNIT_TIME, B_UNIT_CAMERA);
+}
- if (usys == NULL || usys->units[0].name == NULL)
- usys = &buDummyCollection;
+typedef struct {
+ int system;
+ int rotation;
+ /* USER_UNIT_ADAPTIVE means none, otherwise the value is the index in the collection */
+ int length;
+ int mass;
+ int time;
+} PreferredUnits;
- /* split output makes sense only for length, mass and time */
- if (split && (type == B_UNIT_LENGTH || type == B_UNIT_MASS || type == B_UNIT_TIME || type == B_UNIT_CAMERA)) {
- const bUnitDef *unit_a, *unit_b;
- double value_a, value_b;
+static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *settings)
+{
+ PreferredUnits units = { 0 };
+ units.system = settings->system;
+ units.rotation = settings->system_rotation;
+ units.length = settings->length_unit;
+ units.mass = settings->mass_unit;
+ units.time = settings->time_unit;
+ return units;
+}
- unit_dual_convert(value, usys, &unit_a, &unit_b, &value_a, &value_b);
+static size_t unit_as_string_splitted(
+ char *str, int len_max, double value, int prec,
+ const bUnitCollection *usys, const bUnitDef *main_unit)
+{
+ const bUnitDef *unit_a, *unit_b;
+ double value_a, value_b;
- /* check the 2 is a smaller unit */
- if (unit_b > unit_a) {
- size_t i;
- i = unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0');
+ unit_dual_convert(value, usys, &unit_a, &unit_b, &value_a, &value_b, main_unit);
- prec -= integer_digits_d(value_a / unit_b->scalar) - integer_digits_d(value_b / unit_b->scalar);
- prec = max_ii(prec, 0);
+ /* check the 2 is a smaller unit */
+ if (unit_b > unit_a) {
+ 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++] = ' ';
+ prec -= integer_digits_d(value_a / unit_b->scalar) - integer_digits_d(value_b / unit_b->scalar);
+ prec = max_ii(prec, 0);
- /* use low precision since this is a smaller unit */
- i += unit_as_string(str + i, len_max - i, value_b, prec, usys, unit_b, '\0');
- }
- return i;
+ /* 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 */
+ i += unit_as_string(str + i, len_max - i, value_b, prec, usys, unit_b, '\0');
}
+ return i;
+ }
+
+ return -1;
+}
+
+static bool is_valid_unit_collection(const bUnitCollection *usys)
+{
+ return usys != NULL && usys->units[0].name != NULL;
+}
+
+static const bUnitDef *get_preferred_unit_if_used(int type, PreferredUnits units)
+{
+ const bUnitCollection *usys = unit_get_system(units.system, type);
+ if (!is_valid_unit_collection(usys)) return NULL;
+
+ int max_offset = usys->length - 1;
+
+ switch (type)
+ {
+ case B_UNIT_LENGTH:
+ case B_UNIT_AREA:
+ case B_UNIT_VOLUME:
+ if (units.length == USER_UNIT_ADAPTIVE) return NULL;
+ return usys->units + MIN2(units.length, max_offset);
+ case B_UNIT_MASS:
+ if (units.mass == USER_UNIT_ADAPTIVE) return NULL;
+ return usys->units + MIN2(units.mass, max_offset);
+ case B_UNIT_TIME:
+ if (units.time == USER_UNIT_ADAPTIVE) return NULL;
+ return usys->units + MIN2(units.time, max_offset);
+ case B_UNIT_ROTATION:
+ if (units.rotation == 0) return usys->units + 0;
+ else if (units.rotation == USER_UNIT_ROT_RADIANS) return usys->units + 3;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/* Return the length of the generated string. */
+static size_t unit_as_string_main(
+ char *str, int len_max, double value, int prec,
+ int type, bool split, bool pad, PreferredUnits units)
+{
+ const bUnitCollection *usys = unit_get_system(units.system, type);
+ const bUnitDef *main_unit = NULL;
+
+ if (!is_valid_unit_collection(usys)) {
+ usys = &buDummyCollection;
}
+ else {
+ main_unit = get_preferred_unit_if_used(type, units);
+ }
+
+ if (split && unit_should_be_split(type)) {
+ int length = unit_as_string_splitted(str, len_max, value, prec, usys, main_unit);
+ /* failed when length is negative, fallback to no split */
+ if (length >= 0) return length;
+ }
+
+ return unit_as_string(str, len_max, value, prec, usys, main_unit, pad ? ' ' : '\0');
+}
+
+size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad)
+{
+ PreferredUnits units;
+ units.system = system;
+ units.rotation = 0;
+ units.length = USER_UNIT_ADAPTIVE;
+ units.mass = USER_UNIT_ADAPTIVE;
+ units.time = USER_UNIT_ADAPTIVE;
+ return unit_as_string_main(str, len_max, value, prec, type, split, pad, units);
+}
- return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0');
+size_t bUnit_AsString2(char *str, int len_max, double value, int prec, int type, const UnitSettings *settings, bool pad)
+{
+ bool do_split = (settings->flag & USER_UNIT_OPT_SPLIT) != 0;
+ PreferredUnits units = preferred_units_from_UnitSettings(settings);
+ return unit_as_string_main(str, len_max, value, prec, type, do_split, pad, units);
}
BLI_INLINE bool isalpha_or_utf8(const int ch)
@@ -631,6 +731,27 @@ static const bUnitDef *unit_detect_from_str(const bUnitCollection *usys, const c
return unit;
}
+bool bUnit_ContainsUnit(const char *str, int system, int type)
+{
+ const bUnitCollection *usys = unit_get_system(system, type);
+ if (!is_valid_unit_collection(usys)) return false;
+
+ for (int i = 0; i < usys->length; i++) {
+ if (unit_find(str, usys->units + i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+double bUnit_PreferredUnitScalar(const struct UnitSettings *settings, int type)
+{
+ PreferredUnits units = preferred_units_from_UnitSettings(settings);
+ const bUnitDef *unit = get_preferred_unit_if_used(type, units);
+ if (unit == NULL) return 1.0;
+ else return unit->scalar;
+}
+
/* make a copy of the string that replaces the units with numbers
* this is used before parsing
* This is only used when evaluating user input and can afford to be a bit slower
@@ -649,16 +770,13 @@ static const bUnitDef *unit_detect_from_str(const bUnitCollection *usys, const c
bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
+ if (!is_valid_unit_collection(usys)) return false;
const bUnitDef *unit = NULL, *default_unit;
double scale_pref_base = scale_pref;
char str_tmp[TEMP_STR_SIZE];
bool changed = false;
- if (usys == NULL || usys->units[0].name == NULL) {
- return changed;
- }
-
/* make lowercase */
BLI_str_tolower_ascii(str, len_max);
@@ -824,6 +942,11 @@ int bUnit_GetBaseUnit(const void *usys_pt)
return ((bUnitCollection *)usys_pt)->base_unit;
}
+int bUnit_GetBaseUnitOfType(int system, int type)
+{
+ return unit_get_system(system, type)->base_unit;
+}
+
const char *bUnit_GetName(const void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].name;
@@ -837,3 +960,8 @@ double bUnit_GetScaler(const void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].scalar;
}
+
+bool bUnit_IsSuppressed(const void *usys_pt, int index)
+{
+ return (((bUnitCollection *)usys_pt)->units[index].flag & B_UNIT_DEF_SUPPRESS) != 0;
+} \ No newline at end of file
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index c32cfa433bd..7d059d6f996 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -85,6 +85,7 @@
#include "BKE_object.h"
#include "BKE_cloth.h"
#include "BKE_key.h"
+#include "BKE_unit.h"
#include "BLT_translation.h"
@@ -2132,4 +2133,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ UnitSettings *unit = &scene->unit;
+ if (unit->system != USER_UNIT_NONE) {
+ unit->length_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_LENGTH);
+ unit->mass_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_MASS);
+ }
+ unit->time_unit = bUnit_GetBaseUnitOfType(USER_UNIT_NONE, B_UNIT_TIME);
+ }
+ }
}
diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c
index e81f181d636..d2bfc75a2bf 100644
--- a/source/blender/draw/modes/edit_mesh_mode_text.c
+++ b/source/blender/draw/modes/edit_mesh_mode_text.c
@@ -66,7 +66,6 @@ void DRW_edit_mesh_mode_text_measure_stats(
uchar col[4] = {0, 0, 0, 255}; /* color of the text to draw */
float area; /* area of the face */
float grid = unit->system ? unit->scale_length : v3d->grid;
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
/* when 2 edge-info options are enabled, space apart */
@@ -118,9 +117,9 @@ void DRW_edit_mesh_mode_text_measure_stats(
}
if (unit->system) {
- numstr_len = bUnit_AsString(
- numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
- unit->system, B_UNIT_LENGTH, do_split, false);
+ numstr_len = bUnit_AsString2(
+ numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
+ B_UNIT_LENGTH, unit, false);
}
else {
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
@@ -231,10 +230,10 @@ void DRW_edit_mesh_mode_text_measure_stats(
mul_m4_v3(ob->obmat, vmid);
if (unit->system) {
- numstr_len = bUnit_AsString(
+ numstr_len = bUnit_AsString2(
numstr, sizeof(numstr),
(double)(area * unit->scale_length * unit->scale_length),
- 3, unit->system, B_UNIT_AREA, do_split, false);
+ 3, B_UNIT_AREA, unit, false);
}
else {
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area);
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h
index 00558a3a787..f674a0d87f9 100644
--- a/source/blender/editors/include/ED_numinput.h
+++ b/source/blender/editors/include/ED_numinput.h
@@ -88,4 +88,6 @@ bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event
#define NUM_MODAL_INCREMENT_UP 18
#define NUM_MODAL_INCREMENT_DOWN 19
+bool user_string_to_number(bContext *C, const char *str, const struct UnitSettings *unit, int type, double *r_value);
+
#endif /* __ED_NUMINPUT_H__ */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 312d41b796d..dcd09f0d4b0 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -80,6 +80,7 @@
#include "BPY_extern.h"
#include "ED_screen.h"
+#include "ED_numinput.h"
#include "IMB_colormanagement.h"
@@ -2177,7 +2178,6 @@ void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, bool pad, int float_precision)
{
UnitSettings *unit = but->block->unit;
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
int unit_type = UI_but_unit_type_get(but);
int precision;
@@ -2194,9 +2194,9 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
precision = float_precision;
}
- bUnit_AsString(
+ bUnit_AsString2(
str, len_max, ui_get_but_scale_unit(but, value), precision,
- unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type), do_split, pad);
+ RNA_SUBTYPE_UNIT_VALUE(unit_type), unit, pad);
}
static float ui_get_but_step_unit(uiBut *but, float step_default)
@@ -2406,27 +2406,13 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
return str;
}
-#ifdef WITH_PYTHON
-
static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value)
{
- char str_unit_convert[256];
- const int unit_type = UI_but_unit_type_get(but);
-
- BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
-
- /* ugly, use the draw string to get the value,
- * this could cause problems if it includes some text which resolves to a unit */
- bUnit_ReplaceString(
- str_unit_convert, sizeof(str_unit_convert), but->drawstr,
- ui_get_but_scale_unit(but, 1.0), but->block->unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
-
- return BPY_execute_string_as_number(C, NULL, str_unit_convert, true, r_value);
+ const UnitSettings *unit = but->block->unit;
+ int type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
+ return user_string_to_number(C, str, unit, type, r_value);
}
-#endif /* WITH_PYTHON */
-
-
bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value)
{
bool ok = false;
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index fb125a3845b..1dae076f930 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -158,9 +158,6 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
Scene *scene = CTX_data_scene(C);
- UnitSettings *unit = &scene->unit;
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
-
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
@@ -199,9 +196,9 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
*r_depth = len_v3v3(view_co, co_align);
- bUnit_AsString(ddr->name, sizeof(ddr->name),
- (double)*r_depth,
- 4, unit->system, B_UNIT_LENGTH, do_split, false);
+ bUnit_AsString2(
+ ddr->name, sizeof(ddr->name), (double)*r_depth,
+ 4, B_UNIT_LENGTH, &scene->unit, false);
}
else {
BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 62f66334516..a3bd1b26a01 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -164,8 +164,6 @@ static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *rul
static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
char *numstr, size_t numstr_size, int prec)
{
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
-
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
ruler_item->co[1],
@@ -175,9 +173,9 @@ static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
}
else {
- bUnit_AsString(numstr, numstr_size,
- (double)ruler_angle,
- prec, unit->system, B_UNIT_ROTATION, do_split, false);
+ bUnit_AsString2(
+ numstr, numstr_size, (double)ruler_angle,
+ prec, B_UNIT_ROTATION, unit, false);
}
}
else {
@@ -188,9 +186,9 @@ static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
}
else {
- bUnit_AsString(numstr, numstr_size,
- (double)(ruler_len * unit->scale_length),
- prec, unit->system, B_UNIT_LENGTH, do_split, false);
+ bUnit_AsString2(
+ numstr, numstr_size, (double)(ruler_len * unit->scale_length),
+ prec, B_UNIT_LENGTH, unit, false);
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index d6637c2209e..ae57700653a 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -159,7 +159,6 @@ static void ruler_item_active_set(RulerInfo *ruler_info, RulerItem *ruler_item)
static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
char *numstr, size_t numstr_size, int prec)
{
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
@@ -170,9 +169,9 @@ static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
}
else {
- bUnit_AsString(numstr, numstr_size,
- (double)ruler_angle,
- prec, unit->system, B_UNIT_ROTATION, do_split, false);
+ bUnit_AsString2(
+ numstr, numstr_size, (double)ruler_angle,
+ prec, B_UNIT_ROTATION, unit, false);
}
}
else {
@@ -183,9 +182,9 @@ static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
}
else {
- bUnit_AsString(numstr, numstr_size,
- (double)(ruler_len * unit->scale_length),
- prec, unit->system, B_UNIT_LENGTH, do_split, false);
+ bUnit_AsString2(
+ numstr, numstr_size, (double)(ruler_len * unit->scale_length),
+ prec, B_UNIT_LENGTH, unit, false);
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 55fa1fb78c6..61a80e900e1 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4671,12 +4671,12 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
dist = len_v3(vec);
if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- const bool do_split = (t->scene->unit.flag & USER_UNIT_OPT_SPLIT) != 0;
int i;
for (i = 0; i < 3; i++) {
- bUnit_AsString(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length,
- 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, true);
+ bUnit_AsString2(
+ &tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length,
+ 4, B_UNIT_LENGTH, &t->scene->unit, true);
}
}
else {
@@ -4687,9 +4687,9 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
}
if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- const bool do_split = (t->scene->unit.flag & USER_UNIT_OPT_SPLIT) != 0;
- bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system,
- B_UNIT_LENGTH, do_split, false);
+ bUnit_AsString2(
+ distvec, sizeof(distvec), dist * t->scene->unit.scale_length,
+ 4, B_UNIT_LENGTH, &t->scene->unit, false);
}
else if (dist > 1e10f || dist < -1e10f) {
/* prevent string buffer overflow */
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 98e7e5ba897..887c85300d1 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -254,6 +254,32 @@ static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf
return true;
}
+bool user_string_to_number(bContext *C, const char *str, const UnitSettings *unit, int type, double *r_value)
+{
+#ifdef WITH_PYTHON
+ double unit_scale = BKE_scene_unit_scale(unit, type, 1.0);
+ if (!bUnit_ContainsUnit(str, unit->system, type)) {
+ int success = BPY_execute_string_as_number(C, NULL, str, true, r_value);
+ *r_value *= bUnit_PreferredUnitScalar(unit, type);
+ *r_value /= unit_scale;
+ return success;
+ }
+ else {
+ char str_unit_convert[256];
+ BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
+ bUnit_ReplaceString(
+ str_unit_convert, sizeof(str_unit_convert), str,
+ unit_scale, unit->system, type);
+
+ return BPY_execute_string_as_number(C, NULL, str_unit_convert, true, r_value);
+ }
+#else
+ *r_value = atof(str);
+ return true;
+#endif
+}
+
+
static bool editstr_is_simple_numinput(const char ascii)
{
if (ascii >= '0' && ascii <= '9') {
@@ -519,38 +545,18 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
/* At this point, our value has changed, try to interpret it with python (if str is not empty!). */
if (n->str[0]) {
const float val_prev = n->val[idx];
- double val;
-#ifdef WITH_PYTHON
Scene *sce = CTX_data_scene(C);
- 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)BKE_scene_unit_scale(&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";
- }
-
- BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert));
-
- bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, fac,
- n->unit_sys, n->unit_type[idx]);
+ double val;
+ int success = user_string_to_number(C, n->str, &sce->unit, n->unit_type[idx], &val);
- /* Note: with angles, we always get values as radians here... */
- if (BPY_execute_string_as_number(C, NULL, str_unit_convert, false, &val)) {
+ if (success) {
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... */
- val = atof(n->str);
- n->val[idx] = (float)val;
- UNUSED_VARS(C);
-#endif /* WITH_PYTHON */
+ }
#ifdef USE_FAKE_EDIT
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 0bc0fb28d2f..15e8f950686 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1387,6 +1387,12 @@ typedef struct UnitSettings {
char system; /* imperial, metric etc */
char system_rotation; /* not implemented as a proper unit system yet */
short flag;
+
+ char length_unit;
+ char mass_unit;
+ char time_unit;
+
+ char pad[5];
} UnitSettings;
/* ------------------------------------------- */
@@ -2156,6 +2162,7 @@ typedef enum eGPencil_Selectmode_types {
/* UnitSettings */
+#define USER_UNIT_ADAPTIVE 0xFF
/* UnitSettings.system */
#define USER_UNIT_NONE 0
#define USER_UNIT_METRIC 1
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 81e144925be..11d56206d6e 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -515,6 +515,7 @@ const EnumPropertyItem rna_enum_transform_orientation_items[] = {
#include "BKE_animsys.h"
#include "BKE_freestyle.h"
#include "BKE_gpencil.h"
+#include "BKE_unit.h"
#include "ED_info.h"
#include "ED_node.h"
@@ -2015,6 +2016,68 @@ const EnumPropertyItem *rna_TransformOrientation_itemf(
return item;
}
+static const EnumPropertyItem *get_unit_enum_items(int system, int type, bool *r_free)
+{
+ const void *usys;
+ int len;
+ bUnit_GetSystem(system, type, &usys, &len);
+
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
+
+ EnumPropertyItem adaptive = { 0 };
+ adaptive.identifier = "ADAPTIVE";
+ adaptive.name = "Adaptive";
+ adaptive.value = USER_UNIT_ADAPTIVE;
+ RNA_enum_item_add(&items, &totitem, &adaptive);
+
+ for (int i = 0; i < len; i++) {
+ if (!bUnit_IsSuppressed(usys, i)) {
+ EnumPropertyItem tmp = { 0 };
+ tmp.identifier = bUnit_GetName(usys, i);
+ tmp.name = bUnit_GetNameDisplay(usys, i);
+ tmp.value = i;
+ RNA_enum_item_add(&items, &totitem, &tmp);
+ }
+ }
+
+ *r_free = true;
+ return items;
+}
+
+const EnumPropertyItem *rna_get_length_unit_items(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ UnitSettings *units = ptr->data;
+ return get_unit_enum_items(units->system, B_UNIT_LENGTH, r_free);
+}
+
+const EnumPropertyItem *rna_get_mass_unit_items(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ UnitSettings *units = ptr->data;
+ return get_unit_enum_items(units->system, B_UNIT_MASS, r_free);
+}
+
+const EnumPropertyItem *rna_get_time_unit_items(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ UnitSettings *units = ptr->data;
+ return get_unit_enum_items(units->system, B_UNIT_TIME, r_free);
+}
+
+static void rna_unit_system_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ UnitSettings *unit = &scene->unit;
+ if (unit->system == USER_UNIT_NONE) {
+ unit->length_unit = USER_UNIT_ADAPTIVE;
+ unit->mass_unit = USER_UNIT_ADAPTIVE;
+ }
+ else {
+ unit->length_unit = bUnit_GetBaseUnitOfType(unit->system, B_UNIT_LENGTH);
+ unit->mass_unit = bUnit_GetBaseUnitOfType(unit->system, B_UNIT_MASS);
+ }
+}
#else
@@ -2915,7 +2978,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
}
-static void rna_def_unit_settings(BlenderRNA *brna)
+static void rna_def_unit_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -2940,7 +3003,7 @@ static void rna_def_unit_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "system", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, unit_systems);
RNA_def_property_ui_text(prop, "Unit System", "The unit system to use for button display");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
+ RNA_def_property_update(prop, NC_WINDOW, "rna_unit_system_update");
prop = RNA_def_property(srna, "system_rotation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rotation_units);
@@ -2948,7 +3011,9 @@ static void rna_def_unit_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop = RNA_def_property(srna, "scale_length", PROP_FLOAT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Unit Scale", "Scale to use when converting between blender units and dimensions");
+ RNA_def_property_ui_text(prop, "Unit Scale", "Scale to use when converting between blender units and dimensions."
+ " When working at microscopic or astronomical scale, a small or large unit scale"
+ " respectively can be used to avoid numerical precision problems");
RNA_def_property_range(prop, 0.00001, 100000.0);
RNA_def_property_ui_range(prop, 0.001, 100.0, 0.1, 6);
RNA_def_property_update(prop, NC_WINDOW, NULL);
@@ -2957,6 +3022,24 @@ static void rna_def_unit_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_UNIT_OPT_SPLIT);
RNA_def_property_ui_text(prop, "Separate Units", "Display units in pairs (e.g. 1m 0cm)");
RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ prop = RNA_def_property(srna, "length_unit", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_get_length_unit_items");
+ RNA_def_property_ui_text(prop, "Length Unit", "Unit that will be used to display length values");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ prop = RNA_def_property(srna, "mass_unit", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_get_mass_unit_items");
+ RNA_def_property_ui_text(prop, "Mass Unit", "Unit that will be used to display mass values");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ prop = RNA_def_property(srna, "time_unit", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_get_time_unit_items");
+ RNA_def_property_ui_text(prop, "Time Unit", "Unit that will be used to display time values");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
}
void rna_def_view_layer_common(StructRNA *srna, int scene)