diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_unit.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 104 | ||||
-rw-r--r-- | source/blender/editors/util/numinput.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_types.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/makesrna.c | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rna.c | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 16 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 1 |
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}, |