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:
authorHans Goudey <h.goudey@me.com>2020-09-07 22:59:07 +0300
committerHans Goudey <h.goudey@me.com>2020-09-07 22:59:07 +0300
commit36aeb0ec1e2ec8cd6a3690ac11cd3c50f3851802 (patch)
tree4c9ce5df6ba5cc01eb2e0841c57fd9b0e9690b11 /source
parentd4cca7b7b0d858a45c684fd0725344881e0c1c63 (diff)
UI: Add temperature units
Based on the original patch by Vaishnav S (@padthai), this adds support for temperature units. Initially supported units are Celsius, Kelvin, and Fahrenheit. The units aren't used anywhere with this commit. Those changes should happen in separate patches by adding PROP_TEMPERATURE to RNA property definitions. But it should be ensured that the various solvers and simulations actually properly use real units. The complexity of some of the changes comes from the fact that these units have offsets from each other as well as coefficients. This also makes the implementation in the current unit system troublesome. For example, entering 0C evaluates correctly to 273K, but 0C + 0C doubles that result, because each unit value is evaluated separately. This is quite hard to solve in the general case with Blender's current unit system, though, so it is not handled in this commit. Differential Revision: https://developer.blender.org/D4401
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_unit.h7
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c104
-rw-r--r--source/blender/editors/util/numinput.c2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h3
-rw-r--r--source/blender/makesrna/RNA_types.h4
-rw-r--r--source/blender/makesrna/intern/makesrna.c4
-rw-r--r--source/blender/makesrna/intern/rna_rna.c1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c16
-rw-r--r--source/blender/python/intern/bpy_props.c1
10 files changed, 130 insertions, 14 deletions
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
index a797c5555ff..d47cebb5dc8 100644
--- a/source/blender/blenkernel/BKE_unit.h
+++ b/source/blender/blenkernel/BKE_unit.h
@@ -46,8 +46,8 @@ bool bUnit_ReplaceString(
/* return true if the string contains any valid unit for the given type */
bool bUnit_ContainsUnit(const char *str, int type);
-/* if user does not specify a unit, multiply with this value */
-double bUnit_PreferredInputUnitScalar(const struct UnitSettings *settings, int type);
+/* If user does not specify a unit, this converts it to the unit from the settings. */
+double bUnit_ApplyPreferredUnit(const struct UnitSettings *settings, int 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);
@@ -86,7 +86,8 @@ enum {
B_UNIT_ACCELERATION = 8,
B_UNIT_CAMERA = 9,
B_UNIT_POWER = 10,
- B_UNIT_TYPE_TOT = 11,
+ B_UNIT_TEMPERATURE = 11,
+ B_UNIT_TYPE_TOT = 12,
};
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 00218b1be51..a1f74dddbad 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -157,6 +157,8 @@ static void scene_init_data(ID *id)
scene->unit.length_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_LENGTH);
scene->unit.mass_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_MASS);
scene->unit.time_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_TIME);
+ scene->unit.temperature_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC,
+ B_UNIT_TEMPERATURE);
/* Anti-Aliasing threshold. */
scene->grease_pencil_settings.smaa_threshold = 1.0f;
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 5af24152972..c5782d846bb 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -80,6 +80,8 @@
#define UN_SC_LB 0.45359237f
#define UN_SC_OZ 0.028349523125f
+#define UN_SC_FAH 0.555555555555f
+
/* clang-format on */
/* Define a single unit. */
@@ -101,7 +103,7 @@ typedef struct bUnitDef {
const char *identifier;
double scalar;
- /** Not used yet, needed for converting temperature. */
+ /** Needed for converting temperatures. */
double bias;
int flag;
} bUnitDef;
@@ -329,6 +331,22 @@ static struct bUnitDef buPowerDef[] = {
};
static struct bUnitCollection buPowerCollection = {buPowerDef, 3, 0, UNIT_COLLECTION_LENGTH(buPowerDef)};
+/* Temperature */
+static struct bUnitDef buMetricTempDef[] = {
+ {"kelvin", "kelvin", "K", NULL, "Kelvin", "KELVIN", 1.0f, 0.0, B_UNIT_DEF_NONE}, /* Base unit. */
+ {"celsius", "celsius", "°C", "C", "Celsius", "CELCIUS", 1.0f, 273.15, B_UNIT_DEF_NONE},
+ NULL_UNIT,
+};
+static struct bUnitCollection buMetricTempCollection = {buMetricTempDef, 0, 0, UNIT_COLLECTION_LENGTH(buMetricTempDef)};
+
+static struct bUnitDef buImperialTempDef[] = {
+ {"kelvin", "kelvin", "K", NULL, "Kelvin", "KELVIN", 1.0f, 0.0, B_UNIT_DEF_NONE}, /* Base unit. */
+ {"fahrenheit", "fahrenheit", "°F", "F", "Fahrenheit", "FAHRENHEIT", UN_SC_FAH, 459.67, B_UNIT_DEF_NONE},
+ NULL_UNIT,
+};
+static struct bUnitCollection buImperialTempCollection = {
+ buImperialTempDef, 1, 0, UNIT_COLLECTION_LENGTH(buImperialTempDef)};
+
/* clang-format on */
#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1)
@@ -344,6 +362,7 @@ static const struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = {
NULL,
NULL,
NULL,
+ NULL,
NULL},
/* Metric. */
{NULL,
@@ -356,7 +375,8 @@ static const struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = {
&buMetricVelCollection,
&buMetricAclCollection,
&buCameraLenCollection,
- &buPowerCollection},
+ &buPowerCollection,
+ &buMetricTempCollection},
/* Imperial. */
{NULL,
&buImperialLenCollection,
@@ -368,7 +388,8 @@ static const struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = {
&buImperialVelCollection,
&buImperialAclCollection,
&buCameraLenCollection,
- &buPowerCollection},
+ &buPowerCollection,
+ &buImperialTempCollection},
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
@@ -449,7 +470,7 @@ static size_t unit_as_string(char *str,
}
}
- double value_conv = value / unit->scalar;
+ double value_conv = (value / unit->scalar) - unit->bias;
/* Adjust precision to expected number of significant digits.
* Note that here, we shall not have to worry about very big/small numbers, units are expected
@@ -512,6 +533,7 @@ typedef struct {
int length;
int mass;
int time;
+ int temperature;
} PreferredUnits;
static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *settings)
@@ -522,6 +544,7 @@ static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *sett
units.length = settings->length_unit;
units.mass = settings->mass_unit;
units.time = settings->time_unit;
+ units.temperature = settings->temperature_unit;
return units;
}
@@ -597,6 +620,11 @@ static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUni
return usys->units + 3;
}
break;
+ case B_UNIT_TEMPERATURE:
+ if (units.temperature == USER_UNIT_ADAPTIVE) {
+ return NULL;
+ }
+ return usys->units + MIN2(units.temperature, max_offset);
default:
break;
}
@@ -643,6 +671,7 @@ size_t bUnit_AsString(
units.length = USER_UNIT_ADAPTIVE;
units.mass = USER_UNIT_ADAPTIVE;
units.time = USER_UNIT_ADAPTIVE;
+ units.temperature = USER_UNIT_ADAPTIVE;
return unit_as_string_main(str, len_max, value, prec, type, split, pad, units);
}
@@ -844,6 +873,35 @@ static bool unit_distribute_negatives(char *str, const int len_max)
return changed;
}
+/**
+ * Helper for #unit_scale_str for the process of correctly applying the order of operations
+ * for the unit's bias term.
+ */
+static int find_previous_non_value_char(const char *str, const int start_ofs)
+{
+ for (int i = start_ofs; i > 0; i--) {
+ if (ch_is_op(str[i - 1]) || strchr("( )", str[i - 1])) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Helper for #unit_scale_str for the process of correctly applying the order of operations
+ * for the unit's bias term.
+ */
+static int find_end_of_value_chars(const char *str, const int len_max, const int start_ofs)
+{
+ int i;
+ for (i = start_ofs; i < len_max; i++) {
+ if (!strchr("0123456789eE.", str[i])) {
+ return i;
+ }
+ }
+ return i;
+}
+
static int unit_scale_str(char *str,
int len_max,
char *str_tmp,
@@ -867,6 +925,34 @@ static int unit_scale_str(char *str,
int len = strlen(str);
+ /* Deal with unit bias for temperature units. Order of operations is important, so we
+ * have to add parentheses, add the bias, then multiply by the scalar like usual.
+ *
+ * Note: If these changes don't fit in the buffer properly unit evaluation has failed,
+ * just try not to destroy anything while failing. */
+ if (unit->bias != 0.0) {
+ /* Add the open parenthesis. */
+ int prev_op_ofs = find_previous_non_value_char(str, found_ofs);
+ if (len + 1 < len_max) {
+ memmove(str + prev_op_ofs + 1, str + prev_op_ofs, len - prev_op_ofs + 1);
+ str[prev_op_ofs] = '(';
+ len++;
+ found_ofs++;
+ str_found++;
+ } /* If this doesn't fit, we have failed. */
+
+ /* Add the addition sign, the bias, and the close parenthesis after the value. */
+ int value_end_ofs = find_end_of_value_chars(str, len_max, prev_op_ofs + 2);
+ int len_bias_num = BLI_snprintf(str_tmp, TEMP_STR_SIZE, "+%.9g)", unit->bias);
+ if (value_end_ofs + len_bias_num < len_max) {
+ memmove(str + value_end_ofs + len_bias_num, str + value_end_ofs, len - value_end_ofs + 1);
+ memcpy(str + value_end_ofs, str_tmp, len_bias_num);
+ len += len_bias_num;
+ found_ofs += len_bias_num;
+ str_found += len_bias_num;
+ } /* If this doesn't fit, we have failed. */
+ }
+
int len_name = strlen(replace_str);
int len_move = (len - (found_ofs + len_name)) + 1; /* 1+ to copy the string terminator. */
@@ -990,15 +1076,15 @@ bool bUnit_ContainsUnit(const char *str, int type)
return false;
}
-double bUnit_PreferredInputUnitScalar(const struct UnitSettings *settings, int type)
+double bUnit_ApplyPreferredUnit(const struct UnitSettings *settings, int type, double value)
{
PreferredUnits units = preferred_units_from_UnitSettings(settings);
const bUnitDef *unit = get_preferred_display_unit_if_used(type, units);
- if (unit) {
- return unit->scalar;
- }
- return bUnit_BaseScalar(units.system, type);
+ const double scalar = (unit == NULL) ? bUnit_BaseScalar(units.system, type) : unit->scalar;
+ const double bias = (unit == NULL) ? 0.0 : unit->bias; /* Base unit shouldn't have a bias. */
+
+ return value * scalar + bias;
}
/**
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 041b2fec00b..f8e3dda0ed3 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -298,7 +298,7 @@ bool user_string_to_number(bContext *C,
}
int success = BPY_run_string_as_number(C, NULL, str, error_prefix, r_value);
- *r_value *= bUnit_PreferredInputUnitScalar(unit, type);
+ *r_value = bUnit_ApplyPreferredUnit(unit, type, *r_value);
*r_value /= unit_scale;
return success;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 219a7afa6c2..1a63c532c68 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1534,8 +1534,9 @@ typedef struct UnitSettings {
char length_unit;
char mass_unit;
char time_unit;
+ char temperature_unit;
- char _pad[5];
+ char _pad[4];
} UnitSettings;
/* ------------------------------------------- */
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index ee7c045ebf9..1c488b2cac1 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -91,6 +91,7 @@ typedef enum PropertyUnit {
PROP_UNIT_ACCELERATION = (8 << 16), /* m/(s^2) */
PROP_UNIT_CAMERA = (9 << 16), /* mm */
PROP_UNIT_POWER = (10 << 16), /* W */
+ PROP_UNIT_TEMPERATURE = (11 << 16), /* C */
} PropertyUnit;
#define RNA_SUBTYPE_UNIT(subtype) ((subtype)&0x00FF0000)
@@ -156,6 +157,9 @@ typedef enum PropertySubType {
/** Light */
PROP_POWER = 42 | PROP_UNIT_POWER,
+
+ /* temperature */
+ PROP_TEMPERATURE = 43 | PROP_UNIT_TEMPERATURE,
} PropertySubType;
/* Make sure enums are updated with these */
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 2b1e5b3c702..a81bd4d0832 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3199,6 +3199,8 @@ static const char *rna_property_subtypename(PropertySubType type)
return "PROP_PASSWORD";
case PROP_POWER:
return "PROP_POWER";
+ case PROP_TEMPERATURE:
+ return "PROP_TEMPERATURE";
default: {
/* in case we don't have a type preset that includes the subtype */
if (RNA_SUBTYPE_UNIT(type)) {
@@ -3236,6 +3238,8 @@ static const char *rna_property_subtype_unit(PropertySubType type)
return "PROP_UNIT_CAMERA";
case PROP_UNIT_POWER:
return "PROP_UNIT_POWER";
+ case PROP_UNIT_TEMPERATURE:
+ return "PROP_UNIT_TEMPERATURE";
default:
return "PROP_UNIT_UNKNOWN";
}
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 9f5440be9f8..c7076d6c631 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -117,6 +117,7 @@ const EnumPropertyItem rna_enum_property_unit_items[] = {
{PROP_UNIT_MASS, "MASS", 0, "Mass", ""},
{PROP_UNIT_CAMERA, "CAMERA", 0, "Camera", ""},
{PROP_UNIT_POWER, "POWER", 0, "Power", ""},
+ {PROP_UNIT_TEMPERATURE, "TEMPERATURE", 0, "Temperature", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 65edaf0bcca..ab4ffda8888 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2568,6 +2568,15 @@ const EnumPropertyItem *rna_UnitSettings_time_unit_itemf(bContext *UNUSED(C),
return rna_UnitSettings_itemf_wrapper(units->system, B_UNIT_TIME, r_free);
}
+const EnumPropertyItem *rna_UnitSettings_temperature_unit_itemf(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ UnitSettings *units = ptr->data;
+ return rna_UnitSettings_itemf_wrapper(units->system, B_UNIT_TEMPERATURE, r_free);
+}
+
static void rna_UnitSettings_system_update(Main *UNUSED(bmain),
Scene *scene,
PointerRNA *UNUSED(ptr))
@@ -3906,6 +3915,13 @@ static void rna_def_unit_settings(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_UnitSettings_time_unit_itemf");
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);
+
+ prop = RNA_def_property(srna, "temperature_unit", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_UnitSettings_temperature_unit_itemf");
+ RNA_def_property_ui_text(
+ prop, "Temperature Unit", "Unit that will be used to display temperature values");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
}
static void rna_def_view_layer_eevee(BlenderRNA *brna)
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index a78ed601d57..bc708bd4a89 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -172,6 +172,7 @@ static const EnumPropertyItem property_subtype_array_items[] = {
{PROP_LAYER, "LAYER", 0, "Layer", ""},
{PROP_LAYER_MEMBER, "LAYER_MEMBER", 0, "Layer Member", ""},
{PROP_POWER, "POWER", 0, "Power", ""},
+ {PROP_TEMPERATURE, "TEMPERATURE", 0, "Temperature", ""},
{PROP_NONE, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL},