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:
Diffstat (limited to 'source/blender/blenkernel/intern/unit.c')
-rw-r--r--source/blender/blenkernel/intern/unit.c152
1 files changed, 119 insertions, 33 deletions
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 5af24152972..bfa031f0d64 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;
}
@@ -634,7 +662,7 @@ static size_t unit_as_string_main(char *str,
return unit_as_string(str, len_max, value, prec, usys, main_unit, pad ? ' ' : '\0');
}
-size_t bUnit_AsString(
+size_t BKE_unit_value_as_string_adaptive(
char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad)
{
PreferredUnits units;
@@ -643,16 +671,17 @@ 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);
}
-size_t bUnit_AsString2(char *str,
- int len_max,
- double value,
- int prec,
- int type,
- const UnitSettings *settings,
- bool pad)
+size_t BKE_unit_value_as_string(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);
@@ -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. */
@@ -973,7 +1059,7 @@ static const bUnitDef *unit_detect_from_str(const bUnitCollection *usys,
return unit;
}
-bool bUnit_ContainsUnit(const char *str, int type)
+bool BKE_unit_string_contains_unit(const char *str, int type)
{
for (int system = 0; system < UNIT_SYSTEM_TOT; system++) {
const bUnitCollection *usys = unit_get_system(system, type);
@@ -990,15 +1076,15 @@ bool bUnit_ContainsUnit(const char *str, int type)
return false;
}
-double bUnit_PreferredInputUnitScalar(const struct UnitSettings *settings, int type)
+double BKE_unit_apply_preferred_unit(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) ? BKE_unit_base_scalar(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;
}
/**
@@ -1013,11 +1099,11 @@ double bUnit_PreferredInputUnitScalar(const struct UnitSettings *settings, int t
* Values will be split by an add sign.
* 5'2" -> 5*0.3048 + 2*0.0254
*
- * \param str_prev is optional, when valid it is used to get a base unit when none is set.
+ * \param str_prev: is optional, when valid it is used to get a base unit when none is set.
*
* \return True of a change was made.
*/
-bool bUnit_ReplaceString(
+bool BKE_unit_replace_string(
char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
@@ -1047,7 +1133,7 @@ bool bUnit_ReplaceString(
}
else {
/* BLI_snprintf would not fit into str_tmp, cant do much in this case.
- * Check for this because otherwise bUnit_ReplaceString could call its self forever. */
+ * Check for this because otherwise BKE_unit_replace_string could call its self forever. */
return changed;
}
@@ -1108,7 +1194,7 @@ bool bUnit_ReplaceString(
}
/* 45µm --> 45um */
-void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int system, int type)
+void BKE_unit_name_to_alt(char *str, int len_max, const char *orig_str, int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
@@ -1148,7 +1234,7 @@ void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int syste
strncpy(str, orig_str, len_max);
}
-double bUnit_ClosestScalar(double value, int system, int type)
+double BKE_unit_closest_scalar(double value, int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
@@ -1164,7 +1250,7 @@ double bUnit_ClosestScalar(double value, int system, int type)
return unit->scalar;
}
-double bUnit_BaseScalar(int system, int type)
+double BKE_unit_base_scalar(int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
if (usys) {
@@ -1174,12 +1260,12 @@ double bUnit_BaseScalar(int system, int type)
return 1.0;
}
-bool bUnit_IsValid(int system, int type)
+bool BKE_unit_is_valid(int system, int type)
{
return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT);
}
-void bUnit_GetSystem(int system, int type, void const **r_usys_pt, int *r_len)
+void BKE_unit_system_get(int system, int type, void const **r_usys_pt, int *r_len)
{
const bUnitCollection *usys = unit_get_system(system, type);
*r_usys_pt = usys;
@@ -1192,25 +1278,25 @@ void bUnit_GetSystem(int system, int type, void const **r_usys_pt, int *r_len)
*r_len = usys->length;
}
-int bUnit_GetBaseUnit(const void *usys_pt)
+int BKE_unit_base_get(const void *usys_pt)
{
return ((bUnitCollection *)usys_pt)->base_unit;
}
-int bUnit_GetBaseUnitOfType(int system, int type)
+int BKE_unit_base_of_type_get(int system, int type)
{
return unit_get_system(system, type)->base_unit;
}
-const char *bUnit_GetName(const void *usys_pt, int index)
+const char *BKE_unit_name_get(const void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].name;
}
-const char *bUnit_GetNameDisplay(const void *usys_pt, int index)
+const char *BKE_unit_display_name_get(const void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].name_display;
}
-const char *bUnit_GetIdentifier(const void *usys_pt, int index)
+const char *BKE_unit_identifier_get(const void *usys_pt, int index)
{
const bUnitDef *unit = ((const bUnitCollection *)usys_pt)->units + index;
if (unit->identifier == NULL) {
@@ -1219,12 +1305,12 @@ const char *bUnit_GetIdentifier(const void *usys_pt, int index)
return unit->identifier;
}
-double bUnit_GetScaler(const void *usys_pt, int index)
+double BKE_unit_scalar_get(const void *usys_pt, int index)
{
return ((bUnitCollection *)usys_pt)->units[index].scalar;
}
-bool bUnit_IsSuppressed(const void *usys_pt, int index)
+bool BKE_unit_is_suppressed(const void *usys_pt, int index)
{
return (((bUnitCollection *)usys_pt)->units[index].flag & B_UNIT_DEF_SUPPRESS) != 0;
}