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:
-rw-r--r--release/scripts/presets/units_length/centimeters.py5
-rw-r--r--release/scripts/presets/units_length/feet.py5
-rw-r--r--release/scripts/presets/units_length/inches.py5
-rw-r--r--release/scripts/presets/units_length/kilometers.py5
-rw-r--r--release/scripts/presets/units_length/meters.py5
-rw-r--r--release/scripts/presets/units_length/miles.py5
-rw-r--r--release/scripts/presets/units_length/millimeters.py5
-rw-r--r--release/scripts/startup/bl_operators/presets.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py28
-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
23 files changed, 370 insertions, 201 deletions
diff --git a/release/scripts/presets/units_length/centimeters.py b/release/scripts/presets/units_length/centimeters.py
deleted file mode 100644
index 80d5c3e8890..00000000000
--- a/release/scripts/presets/units_length/centimeters.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'METRIC'
-scene.unit_settings.scale_length = 0.01
diff --git a/release/scripts/presets/units_length/feet.py b/release/scripts/presets/units_length/feet.py
deleted file mode 100644
index 015cb810c4d..00000000000
--- a/release/scripts/presets/units_length/feet.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'IMPERIAL'
-scene.unit_settings.scale_length = 0.3048
diff --git a/release/scripts/presets/units_length/inches.py b/release/scripts/presets/units_length/inches.py
deleted file mode 100644
index 7bdc96329ec..00000000000
--- a/release/scripts/presets/units_length/inches.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'IMPERIAL'
-scene.unit_settings.scale_length = 0.0254
diff --git a/release/scripts/presets/units_length/kilometers.py b/release/scripts/presets/units_length/kilometers.py
deleted file mode 100644
index d2a80e56aaa..00000000000
--- a/release/scripts/presets/units_length/kilometers.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'METRIC'
-scene.unit_settings.scale_length = 1000.0
diff --git a/release/scripts/presets/units_length/meters.py b/release/scripts/presets/units_length/meters.py
deleted file mode 100644
index 831f1f26071..00000000000
--- a/release/scripts/presets/units_length/meters.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'METRIC'
-scene.unit_settings.scale_length = 1.0
diff --git a/release/scripts/presets/units_length/miles.py b/release/scripts/presets/units_length/miles.py
deleted file mode 100644
index 59c1e2b36a9..00000000000
--- a/release/scripts/presets/units_length/miles.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'IMPERIAL'
-scene.unit_settings.scale_length = 1609.344
diff --git a/release/scripts/presets/units_length/millimeters.py b/release/scripts/presets/units_length/millimeters.py
deleted file mode 100644
index b89918f8b1b..00000000000
--- a/release/scripts/presets/units_length/millimeters.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import bpy
-scene = bpy.context.scene
-
-scene.unit_settings.system = 'METRIC'
-scene.unit_settings.scale_length = 0.001
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 5dae38a129f..9cc1591494a 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -652,24 +652,6 @@ class WM_MT_operator_presets(Menu):
preset_operator = "script.execute_preset"
-class AddPresetUnitsLength(AddPresetBase, Operator):
- """Add or remove length units preset"""
- bl_idname = "scene.units_length_preset_add"
- bl_label = "Add Length Units Preset"
- preset_menu = "SCENE_PT_units_length_presets"
-
- preset_defines = [
- "scene = bpy.context.scene"
- ]
-
- preset_values = [
- "scene.unit_settings.system",
- "scene.unit_settings.scale_length",
- ]
-
- preset_subdir = "units_length"
-
-
class AddPresetGpencilBrush(AddPresetBase, Operator):
"""Add or remove grease pencil brush preset"""
bl_idname = "scene.gpencil_brush_preset_add"
@@ -764,7 +746,6 @@ classes = (
AddPresetTrackingCamera,
AddPresetTrackingSettings,
AddPresetTrackingTrackColor,
- AddPresetUnitsLength,
AddPresetGpencilBrush,
AddPresetGpencilMaterial,
ExecutePreset,
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 8e3bfd63726..2cabefe905e 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -33,14 +33,6 @@ from .properties_physics_common import (
)
-class SCENE_PT_units_length_presets(PresetMenu):
- """Unit of measure for properties that use length values"""
- bl_label = "Unit Presets"
- preset_subdir = "units_length"
- preset_operator = "script.execute_preset"
- preset_add_operator = "scene.units_length_preset_add"
-
-
class SCENE_UL_keying_set_paths(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.KeyingSetPath)
@@ -84,9 +76,6 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
bl_label = "Units"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- def draw_header_preset(self, context):
- SCENE_PT_units_length_presets.draw_panel_header(self.layout)
-
def draw(self, context):
layout = self.layout
@@ -95,17 +84,21 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
-
- col = flow.column()
- col.prop(unit, "system")
- col.prop(unit, "system_rotation")
+ layout.prop(unit, "system")
- col = flow.column()
+ col = layout.column()
col.enabled = unit.system != 'NONE'
col.prop(unit, "scale_length")
col.prop(unit, "use_separate")
+ col = layout.column()
+ col.prop(unit, "system_rotation", text="Rotation")
+ subcol = col.column()
+ subcol.enabled = unit.system != 'NONE'
+ subcol.prop(unit, "length_unit", text="Length")
+ subcol.prop(unit, "mass_unit", text="Mass")
+ subcol.prop(unit, "time_unit", text="Time")
+
class SceneKeyingSetsPanel:
@@ -607,7 +600,6 @@ class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
classes = (
- SCENE_PT_units_length_presets,
SCENE_UL_keying_set_paths,
SCENE_PT_scene,
SCENE_PT_unit,
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)