UI: Unit completion hint when text editing #116103
|
@ -24,7 +24,8 @@ size_t BKE_unit_value_as_string_adaptive(char *str,
|
||||||
int system,
|
int system,
|
||||||
int type,
|
int type,
|
||||||
bool split,
|
bool split,
|
||||||
bool pad);
|
bool pad,
|
||||||
|
bool do_suffix);
|
||||||
/**
|
/**
|
||||||
* Representation of a value in units. Negative precision is used to disable stripping of zeroes.
|
* Representation of a value in units. Negative precision is used to disable stripping of zeroes.
|
||||||
* This reduces text jumping when changing values.
|
* This reduces text jumping when changing values.
|
||||||
|
@ -35,7 +36,8 @@ size_t BKE_unit_value_as_string(char *str,
|
||||||
int prec,
|
int prec,
|
||||||
int type,
|
int type,
|
||||||
const UnitSettings *settings,
|
const UnitSettings *settings,
|
||||||
bool pad);
|
bool pad,
|
||||||
|
bool do_suffix);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace units with values, used before python button evaluation.
|
* Replace units with values, used before python button evaluation.
|
||||||
|
@ -95,8 +97,10 @@ bool BKE_unit_is_valid(int system, int type);
|
||||||
void BKE_unit_system_get(int system, int type, const void **r_usys_pt, int *r_len);
|
void BKE_unit_system_get(int system, int type, const void **r_usys_pt, int *r_len);
|
||||||
int BKE_unit_base_get(const void *usys_pt);
|
int BKE_unit_base_get(const void *usys_pt);
|
||||||
int BKE_unit_base_of_type_get(int system, int type);
|
int BKE_unit_base_of_type_get(int system, int type);
|
||||||
|
int BKE_unit_of_type_or_default(const UnitSettings *settings, int type);
|
||||||
const char *BKE_unit_name_get(const void *usys_pt, int index);
|
const char *BKE_unit_name_get(const void *usys_pt, int index);
|
||||||
const char *BKE_unit_display_name_get(const void *usys_pt, int index);
|
const char *BKE_unit_display_name_get(const void *usys_pt, int index);
|
||||||
|
const char *BKE_unit_display_name_short_get(const void *usys_pt, int index);
|
||||||
const char *BKE_unit_identifier_get(const void *usys_pt, int index);
|
const char *BKE_unit_identifier_get(const void *usys_pt, int index);
|
||||||
double BKE_unit_scalar_get(const void *usys_pt, int index);
|
double BKE_unit_scalar_get(const void *usys_pt, int index);
|
||||||
bool BKE_unit_is_suppressed(const void *usys_pt, int index);
|
bool BKE_unit_is_suppressed(const void *usys_pt, int index);
|
||||||
|
|
|
@ -1520,7 +1520,8 @@ static size_t unit_as_string(char *str,
|
||||||
const bUnitCollection *usys,
|
const bUnitCollection *usys,
|
||||||
/* Non exposed options. */
|
/* Non exposed options. */
|
||||||
const bUnitDef *unit,
|
const bUnitDef *unit,
|
||||||
char pad)
|
char pad,
|
||||||
|
const bool do_suffix)
|
||||||
{
|
{
|
||||||
if (unit == nullptr) {
|
if (unit == nullptr) {
|
||||||
if (value == 0.0) {
|
if (value == 0.0) {
|
||||||
|
@ -1572,16 +1573,18 @@ static size_t unit_as_string(char *str,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now add a space for all units except foot, inch, degree, arcminute, arcsecond. */
|
/* Now add a space for all units except foot, inch, degree, arcminute, arcsecond. */
|
||||||
if (!(unit->flag & B_UNIT_DEF_NO_SPACE)) {
|
if (!(unit->flag & B_UNIT_DEF_NO_SPACE) && do_suffix) {
|
||||||
str[++i] = ' ';
|
str[++i] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now add the suffix. */
|
|
||||||
if (i < str_maxncpy) {
|
if (i < str_maxncpy) {
|
||||||
int j = 0;
|
|
||||||
i++;
|
i++;
|
||||||
while (unit->name_short[j] && (i < str_maxncpy)) {
|
if (do_suffix) {
|
||||||
str[i++] = unit->name_short[j++];
|
/* Now add the suffix. */
|
||||||
|
int j = 0;
|
||||||
|
while (unit->name_short[j] && (i < str_maxncpy)) {
|
||||||
|
str[i++] = unit->name_short[j++];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1634,7 +1637,7 @@ static size_t unit_as_string_split_pair(char *str,
|
||||||
|
|
||||||
/* Check the 2 is a smaller unit. */
|
/* Check the 2 is a smaller unit. */
|
||||||
if (unit_b > unit_a) {
|
if (unit_b > unit_a) {
|
||||||
size_t i = unit_as_string(str, str_maxncpy, value_a, prec, usys, unit_a, '\0');
|
size_t i = unit_as_string(str, str_maxncpy, value_a, prec, usys, unit_a, '\0', true);
|
||||||
|
|
||||||
prec -= integer_digits_d(value_a / unit_b->scalar) -
|
prec -= integer_digits_d(value_a / unit_b->scalar) -
|
||||||
integer_digits_d(value_b / unit_b->scalar);
|
integer_digits_d(value_b / unit_b->scalar);
|
||||||
|
@ -1645,7 +1648,7 @@ static size_t unit_as_string_split_pair(char *str,
|
||||||
str[i++] = ' ';
|
str[i++] = ' ';
|
||||||
|
|
||||||
/* Use low precision since this is a smaller unit. */
|
/* Use low precision since this is a smaller unit. */
|
||||||
i += unit_as_string(str + i, str_maxncpy - i, value_b, prec, usys, unit_b, '\0');
|
i += unit_as_string(str + i, str_maxncpy - i, value_b, prec, usys, unit_b, '\0', true);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -1658,11 +1661,11 @@ static bool is_valid_unit_collection(const bUnitCollection *usys)
|
||||||
return usys != nullptr && usys->units[0].name != nullptr;
|
return usys != nullptr && usys->units[0].name != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUnits units)
|
static int get_preferred_display_unit_index_if_used(int type, PreferredUnits units)
|
||||||
{
|
{
|
||||||
const bUnitCollection *usys = unit_get_system(units.system, type);
|
const bUnitCollection *usys = unit_get_system(units.system, type);
|
||||||
if (!is_valid_unit_collection(usys)) {
|
if (!is_valid_unit_collection(usys)) {
|
||||||
return nullptr;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_offset = usys->length - 1;
|
int max_offset = usys->length - 1;
|
||||||
|
@ -1672,36 +1675,46 @@ static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUni
|
||||||
case B_UNIT_AREA:
|
case B_UNIT_AREA:
|
||||||
case B_UNIT_VOLUME:
|
case B_UNIT_VOLUME:
|
||||||
if (units.length == USER_UNIT_ADAPTIVE) {
|
if (units.length == USER_UNIT_ADAPTIVE) {
|
||||||
return nullptr;
|
return -1;
|
||||||
}
|
}
|
||||||
return usys->units + std::min(units.length, max_offset);
|
return std::min(units.length, max_offset);
|
||||||
case B_UNIT_MASS:
|
case B_UNIT_MASS:
|
||||||
if (units.mass == USER_UNIT_ADAPTIVE) {
|
if (units.mass == USER_UNIT_ADAPTIVE) {
|
||||||
return nullptr;
|
return -1;
|
||||||
}
|
}
|
||||||
return usys->units + std::min(units.mass, max_offset);
|
return std::min(units.mass, max_offset);
|
||||||
case B_UNIT_TIME:
|
case B_UNIT_TIME:
|
||||||
if (units.time == USER_UNIT_ADAPTIVE) {
|
if (units.time == USER_UNIT_ADAPTIVE) {
|
||||||
return nullptr;
|
return -1;
|
||||||
}
|
}
|
||||||
return usys->units + std::min(units.time, max_offset);
|
return std::min(units.time, max_offset);
|
||||||
case B_UNIT_ROTATION:
|
case B_UNIT_ROTATION:
|
||||||
if (units.rotation == 0) {
|
if (units.rotation == 0) {
|
||||||
return usys->units + 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (units.rotation == USER_UNIT_ROT_RADIANS) {
|
else if (units.rotation == USER_UNIT_ROT_RADIANS) {
|
||||||
return usys->units + 3;
|
return 3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_UNIT_TEMPERATURE:
|
case B_UNIT_TEMPERATURE:
|
||||||
if (units.temperature == USER_UNIT_ADAPTIVE) {
|
if (units.temperature == USER_UNIT_ADAPTIVE) {
|
||||||
return nullptr;
|
return -1;
|
||||||
}
|
}
|
||||||
return usys->units + std::min(units.temperature, max_offset);
|
return std::min(units.temperature, max_offset);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUnits units)
|
||||||
|
{
|
||||||
|
const bUnitCollection *usys = unit_get_system(units.system, type);
|
||||||
|
const int index = get_preferred_display_unit_index_if_used(type, units);
|
||||||
|
if (index == -1) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return usys->units + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the length of the generated string. */
|
/* Return the length of the generated string. */
|
||||||
|
@ -1712,6 +1725,7 @@ static size_t unit_as_string_main(char *str,
|
||||||
int type,
|
int type,
|
||||||
bool split,
|
bool split,
|
||||||
bool pad,
|
bool pad,
|
||||||
|
const bool do_suffix,
|
||||||
PreferredUnits units)
|
PreferredUnits units)
|
||||||
{
|
{
|
||||||
const bUnitCollection *usys = unit_get_system(units.system, type);
|
const bUnitCollection *usys = unit_get_system(units.system, type);
|
||||||
|
@ -1732,11 +1746,19 @@ static size_t unit_as_string_main(char *str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return unit_as_string(str, str_maxncpy, value, prec, usys, main_unit, pad ? ' ' : '\0');
|
return unit_as_string(
|
||||||
|
str, str_maxncpy, value, prec, usys, main_unit, pad ? ' ' : '\0', do_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BKE_unit_value_as_string_adaptive(
|
size_t BKE_unit_value_as_string_adaptive(char *str,
|
||||||
char *str, int str_maxncpy, double value, int prec, int system, int type, bool split, bool pad)
|
int str_maxncpy,
|
||||||
|
double value,
|
||||||
|
int prec,
|
||||||
|
int system,
|
||||||
|
int type,
|
||||||
|
bool split,
|
||||||
|
bool pad,
|
||||||
|
const bool do_suffix)
|
||||||
{
|
{
|
||||||
PreferredUnits units;
|
PreferredUnits units;
|
||||||
units.system = system;
|
units.system = system;
|
||||||
|
@ -1745,7 +1767,7 @@ size_t BKE_unit_value_as_string_adaptive(
|
||||||
units.mass = USER_UNIT_ADAPTIVE;
|
units.mass = USER_UNIT_ADAPTIVE;
|
||||||
units.time = USER_UNIT_ADAPTIVE;
|
units.time = USER_UNIT_ADAPTIVE;
|
||||||
units.temperature = USER_UNIT_ADAPTIVE;
|
units.temperature = USER_UNIT_ADAPTIVE;
|
||||||
return unit_as_string_main(str, str_maxncpy, value, prec, type, split, pad, units);
|
return unit_as_string_main(str, str_maxncpy, value, prec, type, split, pad, do_suffix, units);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BKE_unit_value_as_string(char *str,
|
size_t BKE_unit_value_as_string(char *str,
|
||||||
|
@ -1754,11 +1776,12 @@ size_t BKE_unit_value_as_string(char *str,
|
||||||
int prec,
|
int prec,
|
||||||
int type,
|
int type,
|
||||||
const UnitSettings *settings,
|
const UnitSettings *settings,
|
||||||
bool pad)
|
bool pad,
|
||||||
|
const bool do_suffix)
|
||||||
{
|
{
|
||||||
bool do_split = (settings->flag & USER_UNIT_OPT_SPLIT) != 0;
|
bool do_split = (settings->flag & USER_UNIT_OPT_SPLIT) != 0;
|
||||||
PreferredUnits units = preferred_units_from_UnitSettings(settings);
|
PreferredUnits units = preferred_units_from_UnitSettings(settings);
|
||||||
return unit_as_string_main(str, str_maxncpy, value, prec, type, do_split, pad, units);
|
return unit_as_string_main(str, str_maxncpy, value, prec, type, do_split, pad, do_suffix, units);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_INLINE bool isalpha_or_utf8(const int ch)
|
BLI_INLINE bool isalpha_or_utf8(const int ch)
|
||||||
|
@ -2347,6 +2370,16 @@ int BKE_unit_base_of_type_get(int system, int type)
|
||||||
return unit_get_system(system, type)->base_unit;
|
return unit_get_system(system, type)->base_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BKE_unit_of_type_or_default(const UnitSettings *settings, int type)
|
||||||
|
{
|
||||||
|
PreferredUnits units = preferred_units_from_UnitSettings(settings);
|
||||||
|
int unit_index = get_preferred_display_unit_index_if_used(type, units);
|
||||||
|
if (unit_index == -1) {
|
||||||
|
return BKE_unit_base_of_type_get(units.system, type);
|
||||||
|
}
|
||||||
|
return unit_index;
|
||||||
|
}
|
||||||
|
|
||||||
const char *BKE_unit_name_get(const void *usys_pt, int index)
|
const char *BKE_unit_name_get(const void *usys_pt, int index)
|
||||||
{
|
{
|
||||||
const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
|
const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
|
||||||
|
@ -2359,6 +2392,12 @@ const char *BKE_unit_display_name_get(const void *usys_pt, int index)
|
||||||
BLI_assert(uint(index) < uint(usys->length));
|
BLI_assert(uint(index) < uint(usys->length));
|
||||||
return usys->units[index].name_display;
|
return usys->units[index].name_display;
|
||||||
}
|
}
|
||||||
|
const char *BKE_unit_display_name_short_get(const void *usys_pt, int index)
|
||||||
|
{
|
||||||
|
const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
|
||||||
|
BLI_assert(uint(index) < uint(usys->length));
|
||||||
|
return usys->units[index].name_short;
|
||||||
|
}
|
||||||
const char *BKE_unit_identifier_get(const void *usys_pt, int index)
|
const char *BKE_unit_identifier_get(const void *usys_pt, int index)
|
||||||
{
|
{
|
||||||
const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
|
const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
|
||||||
|
|
|
@ -327,7 +327,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
||||||
3,
|
3,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
unit,
|
unit,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
numstr_len = SNPRINTF_RLEN(numstr, conv_float, len_v3v3(v1, v2));
|
numstr_len = SNPRINTF_RLEN(numstr, conv_float, len_v3v3(v1, v2));
|
||||||
|
@ -469,7 +470,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
||||||
3,
|
3,
|
||||||
B_UNIT_AREA,
|
B_UNIT_AREA,
|
||||||
unit,
|
unit,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
numstr_len = SNPRINTF_RLEN(numstr, conv_float, area);
|
numstr_len = SNPRINTF_RLEN(numstr, conv_float, area);
|
||||||
|
|
|
@ -945,6 +945,11 @@ void UI_but_type_set_menu_from_pulldown(uiBut *but);
|
||||||
*/
|
*/
|
||||||
void UI_but_placeholder_set(uiBut *but, const char *placeholder_text) ATTR_NONNULL(1);
|
void UI_but_placeholder_set(uiBut *but, const char *placeholder_text) ATTR_NONNULL(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a completion text that will be displayed while editing.
|
||||||
|
*/
|
||||||
|
void UI_but_completion_set(uiBut *but, const char *completion_text) ATTR_NONNULL(1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special button case, only draw it when used actively, for outliner etc.
|
* Special button case, only draw it when used actively, for outliner etc.
|
||||||
*
|
*
|
||||||
|
|
|
@ -192,7 +192,8 @@ static void depthdropper_depth_sample_pt(bContext *C,
|
||||||
4,
|
4,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
&scene->unit,
|
&scene->unit,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
STRNCPY(ddr->name, "Nothing under cursor");
|
STRNCPY(ddr->name, "Nothing under cursor");
|
||||||
|
|
|
@ -2764,8 +2764,13 @@ void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t str_maxncpy)
|
||||||
/**
|
/**
|
||||||
* \param float_precision: Override the button precision.
|
* \param float_precision: Override the button precision.
|
||||||
*/
|
*/
|
||||||
static void ui_get_but_string_unit(
|
static void ui_get_but_string_unit(uiBut *but,
|
||||||
uiBut *but, char *str, int str_maxncpy, double value, bool pad, int float_precision)
|
char *str,
|
||||||
|
int str_maxncpy,
|
||||||
|
double value,
|
||||||
|
bool pad,
|
||||||
|
int float_precision,
|
||||||
|
const bool do_suffix)
|
||||||
{
|
{
|
||||||
UnitSettings *unit = but->block->unit;
|
UnitSettings *unit = but->block->unit;
|
||||||
const int unit_type = UI_but_unit_type_get(but);
|
const int unit_type = UI_but_unit_type_get(but);
|
||||||
|
@ -2796,7 +2801,8 @@ static void ui_get_but_string_unit(
|
||||||
precision,
|
precision,
|
||||||
RNA_SUBTYPE_UNIT_VALUE(unit_type),
|
RNA_SUBTYPE_UNIT_VALUE(unit_type),
|
||||||
unit,
|
unit,
|
||||||
pad);
|
pad,
|
||||||
|
do_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float ui_get_but_step_unit(uiBut *but, float step_default)
|
static float ui_get_but_step_unit(uiBut *but, float step_default)
|
||||||
|
@ -2928,7 +2934,7 @@ void ui_but_string_get_ex(uiBut *but,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui_but_is_unit(but)) {
|
if (ui_but_is_unit(but)) {
|
||||||
ui_get_but_string_unit(but, str, str_maxncpy, value, false, prec);
|
ui_get_but_string_unit(but, str, str_maxncpy, value, false, prec, false);
|
||||||
}
|
}
|
||||||
else if (subtype == PROP_FACTOR) {
|
else if (subtype == PROP_FACTOR) {
|
||||||
if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
|
if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
|
||||||
|
@ -3486,6 +3492,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
|
||||||
MEM_freeN(but->placeholder);
|
MEM_freeN(but->placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (but->completion) {
|
||||||
|
MEM_freeN(but->completion);
|
||||||
|
}
|
||||||
|
|
||||||
ui_but_free_type_specific(but);
|
ui_but_free_type_specific(but);
|
||||||
|
|
||||||
if (but->active) {
|
if (but->active) {
|
||||||
|
@ -3764,7 +3774,7 @@ static void ui_but_build_drawstr_float(uiBut *but, double value)
|
||||||
}
|
}
|
||||||
else if (ui_but_is_unit(but)) {
|
else if (ui_but_is_unit(but)) {
|
||||||
char new_str[sizeof(but->drawstr)];
|
char new_str[sizeof(but->drawstr)];
|
||||||
ui_get_but_string_unit(but, new_str, sizeof(new_str), value, true, -1);
|
ui_get_but_string_unit(but, new_str, sizeof(new_str), value, true, -1, true);
|
||||||
STR_CONCAT(but->drawstr, slen, new_str);
|
STR_CONCAT(but->drawstr, slen, new_str);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -5967,6 +5977,17 @@ const char *ui_but_placeholder_get(uiBut *but)
|
||||||
return placeholder;
|
return placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UI_but_completion_set(uiBut *but, const char *completion_text)
|
||||||
|
{
|
||||||
|
MEM_SAFE_FREE(but->completion);
|
||||||
|
but->completion = BLI_strdup_null(completion_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ui_but_completion_get(uiBut *but)
|
||||||
|
{
|
||||||
|
return but->completion;
|
||||||
|
}
|
||||||
|
|
||||||
void UI_but_type_set_menu_from_pulldown(uiBut *but)
|
void UI_but_type_set_menu_from_pulldown(uiBut *but)
|
||||||
{
|
{
|
||||||
BLI_assert(but->type == UI_BTYPE_PULLDOWN);
|
BLI_assert(but->type == UI_BTYPE_PULLDOWN);
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
|
|
||||||
#include "IMB_colormanagement.h"
|
#include "IMB_colormanagement.h"
|
||||||
|
|
||||||
|
#include "ED_numinput.hh"
|
||||||
#include "ED_screen.hh"
|
#include "ED_screen.hh"
|
||||||
#include "ED_undo.hh"
|
#include "ED_undo.hh"
|
||||||
|
|
||||||
|
@ -61,6 +62,8 @@
|
||||||
|
|
||||||
#include "BLF_api.h"
|
#include "BLF_api.h"
|
||||||
|
|
||||||
|
#include "BPY_extern_run.h"
|
||||||
|
|
||||||
#include "interface_intern.hh"
|
#include "interface_intern.hh"
|
||||||
|
|
||||||
#include "RNA_access.hh"
|
#include "RNA_access.hh"
|
||||||
|
@ -3426,6 +3429,77 @@ const wmIMEData *ui_but_ime_data_get(uiBut *but)
|
||||||
}
|
}
|
||||||
#endif /* WITH_INPUT_IME */
|
#endif /* WITH_INPUT_IME */
|
||||||
|
|
||||||
|
static void ui_do_but_text_completion(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||||
|
{
|
||||||
|
/* Unit completion (hint) is only done for buttons with a unit or with a property of type
|
||||||
|
* PROP_PIXEL or PROP_PERCENTAGE. For everything else, we reset the completion to nullptr. */
|
||||||
|
if (!ui_but_is_unit(but) &&
|
||||||
|
(but->rnaprop && !ELEM(RNA_property_subtype(but->rnaprop), PROP_PIXEL, PROP_PERCENTAGE)))
|
||||||
|
{
|
||||||
|
UI_but_completion_set(but, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the completion text (hint) to the unit that is used by this value. */
|
||||||
|
std::string name_short;
|
||||||
|
const int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
|
||||||
|
if (unit_type != PROP_NONE) {
|
||||||
|
/* If the string contains the unit already, don't add it as a hint. */
|
||||||
|
if (BKE_unit_string_contains_unit(data->str, unit_type)) {
|
||||||
|
UI_but_completion_set(but, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the number we're entering is not valid, don't show the hint. */
|
||||||
|
double value;
|
||||||
|
if (!BPY_run_string_as_number(C, nullptr, data->str, nullptr, &value)) {
|
||||||
|
UI_but_completion_set(but, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *usys;
|
||||||
|
int len;
|
||||||
|
UnitSettings &unit_settings = CTX_data_scene(C)->unit;
|
||||||
|
BKE_unit_system_get(unit_settings.system, unit_type, &usys, &len);
|
||||||
|
const int unit_index = BKE_unit_of_type_or_default(&unit_settings, unit_type);
|
||||||
|
name_short = BKE_unit_display_name_short_get(usys, unit_index);
|
||||||
|
}
|
||||||
|
else if (but->rnaprop) {
|
||||||
|
/* Special handling for PROP_PIXEL and PROP_PERCENTAGE (because they are not treated as units
|
||||||
|
* unfortunatly). */
|
||||||
|
const PropertySubType subtype = RNA_property_subtype(but->rnaprop);
|
||||||
|
if (ELEM(subtype, PROP_PIXEL, PROP_PERCENTAGE)) {
|
||||||
|
switch (subtype) {
|
||||||
|
case PROP_PIXEL:
|
||||||
|
name_short = "px";
|
||||||
|
break;
|
||||||
|
case PROP_PERCENTAGE:
|
||||||
|
name_short = "%";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the string contains the unit already, don't add it as a hint. */
|
||||||
|
std::string str = data->str;
|
||||||
|
if (str.find(name_short) != std::string::npos) {
|
||||||
|
UI_but_completion_set(but, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the number we're entering is not valid, don't show the hint. */
|
||||||
|
double value;
|
||||||
|
if (!BPY_run_string_as_number(C, nullptr, data->str, nullptr, &value)) {
|
||||||
|
UI_but_completion_set(but, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a space before the short unit name. */
|
||||||
|
std::string text_completion = " " + name_short;
|
||||||
|
UI_but_completion_set(but, text_completion.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||||
{
|
{
|
||||||
wmWindow *win = data->window;
|
wmWindow *win = data->window;
|
||||||
|
@ -3516,6 +3590,9 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||||
|
|
||||||
ui_but_update(but);
|
ui_but_update(but);
|
||||||
|
|
||||||
|
/* Initialize completion. */
|
||||||
|
ui_do_but_text_completion(C, but, data);
|
||||||
|
|
||||||
/* Make sure the edited button is in view. */
|
/* Make sure the edited button is in view. */
|
||||||
if (data->searchbox) {
|
if (data->searchbox) {
|
||||||
/* Popup blocks don't support moving after creation, so don't change the view for them. */
|
/* Popup blocks don't support moving after creation, so don't change the view for them. */
|
||||||
|
@ -4052,6 +4129,9 @@ static void ui_do_but_textedit(
|
||||||
ui_textedit_undo_push(data->undo_stack_text, data->str, but->pos);
|
ui_textedit_undo_push(data->undo_stack_text, data->str, but->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle text completion. */
|
||||||
|
ui_do_but_text_completion(C, but, data);
|
||||||
|
|
||||||
/* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */
|
/* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */
|
||||||
if (update && data->interactive) {
|
if (update && data->interactive) {
|
||||||
ui_apply_but(C, block, but, data, true);
|
ui_apply_but(C, block, but, data, true);
|
||||||
|
|
|
@ -181,6 +181,7 @@ struct uiBut {
|
||||||
char *str = nullptr;
|
char *str = nullptr;
|
||||||
char strdata[UI_MAX_NAME_STR] = "";
|
char strdata[UI_MAX_NAME_STR] = "";
|
||||||
char drawstr[UI_MAX_DRAW_STR] = "";
|
char drawstr[UI_MAX_DRAW_STR] = "";
|
||||||
|
char *completion = nullptr;
|
||||||
|
|
||||||
char *placeholder = nullptr;
|
char *placeholder = nullptr;
|
||||||
|
|
||||||
|
@ -759,6 +760,11 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but);
|
||||||
*/
|
*/
|
||||||
const char *ui_but_placeholder_get(uiBut *but);
|
const char *ui_but_placeholder_get(uiBut *but);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the completion string while editing.
|
||||||
|
*/
|
||||||
|
const char *ui_but_completion_get(uiBut *but);
|
||||||
|
|
||||||
void ui_def_but_icon(uiBut *but, int icon, int flag);
|
void ui_def_but_icon(uiBut *but, int icon, int flag);
|
||||||
/**
|
/**
|
||||||
* Avoid using this where possible since it's better not to ask for an icon in the first place.
|
* Avoid using this where possible since it's better not to ask for an icon in the first place.
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_context.hh"
|
#include "BKE_context.hh"
|
||||||
|
#include "BKE_unit.hh"
|
||||||
|
|
||||||
#include "RNA_access.hh"
|
#include "RNA_access.hh"
|
||||||
|
|
||||||
|
@ -1849,6 +1850,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
|
||||||
const char *drawstr_right = nullptr;
|
const char *drawstr_right = nullptr;
|
||||||
bool use_right_only = false;
|
bool use_right_only = false;
|
||||||
const char *indeterminate_str = UI_VALUE_INDETERMINATE_CHAR;
|
const char *indeterminate_str = UI_VALUE_INDETERMINATE_CHAR;
|
||||||
|
const char *completion = ui_but_completion_get(but);
|
||||||
|
|
||||||
#ifdef WITH_INPUT_IME
|
#ifdef WITH_INPUT_IME
|
||||||
const wmIMEData *ime_data;
|
const wmIMEData *ime_data;
|
||||||
|
@ -1873,6 +1875,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
|
||||||
uiBut *but_edit = ui_but_drag_multi_edit_get(but);
|
uiBut *but_edit = ui_but_drag_multi_edit_get(but);
|
||||||
if (but_edit) {
|
if (but_edit) {
|
||||||
drawstr = but_edit->editstr;
|
drawstr = but_edit->editstr;
|
||||||
|
completion = but_edit->completion;
|
||||||
align = UI_STYLE_TEXT_LEFT;
|
align = UI_STYLE_TEXT_LEFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2177,6 +2180,32 @@ static void widget_draw_text(const uiFontStyle *fstyle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (completion && completion[0] != '\0' && drawstr[0] != '\0') {
|
||||||
|
rcti text_bounds;
|
||||||
|
BLF_boundbox(fstyle->uifont_id, drawstr + but->ofs, drawlen, &text_bounds);
|
||||||
|
|
||||||
|
uiFontStyle style = *fstyle;
|
||||||
|
style.shadow = 0;
|
||||||
|
uchar col[4];
|
||||||
|
copy_v4_v4_uchar(col, wcol->text);
|
||||||
|
col[3] *= 0.33f;
|
||||||
|
|
||||||
|
rcti completion_rect;
|
||||||
|
completion_rect.xmin = rect->xmin + text_bounds.xmax;
|
||||||
|
completion_rect.ymin = rect->ymin;
|
||||||
|
completion_rect.xmax = rect->xmax;
|
||||||
|
completion_rect.ymax = rect->ymax;
|
||||||
|
UI_fontstyle_draw_ex(&style,
|
||||||
|
&completion_rect,
|
||||||
|
completion,
|
||||||
|
strlen(completion),
|
||||||
|
col,
|
||||||
|
¶ms,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
|
||||||
3,
|
3,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
&sce->unit,
|
&sce->unit,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
|
||||||
4,
|
4,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
&sce->unit,
|
&sce->unit,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
BKE_unit_value_as_string(flts_str + NUM_STR_REP_LEN,
|
BKE_unit_value_as_string(flts_str + NUM_STR_REP_LEN,
|
||||||
NUM_STR_REP_LEN,
|
NUM_STR_REP_LEN,
|
||||||
|
@ -99,6 +100,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
|
||||||
4,
|
4,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
&sce->unit,
|
&sce->unit,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
SNPRINTF(msg,
|
SNPRINTF(msg,
|
||||||
|
|
|
@ -520,7 +520,8 @@ static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd)
|
||||||
distance_precision,
|
distance_precision,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
unit,
|
unit,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLF_enable(blf_mono_font, BLF_ROTATION);
|
BLF_enable(blf_mono_font, BLF_ROTATION);
|
||||||
|
@ -649,8 +650,14 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd,
|
||||||
SNPRINTF(numstr, "%.*f" BLI_STR_UTF8_DEGREE_SIGN, angle_precision, RAD2DEGF(angle));
|
SNPRINTF(numstr, "%.*f" BLI_STR_UTF8_DEGREE_SIGN, angle_precision, RAD2DEGF(angle));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BKE_unit_value_as_string(
|
BKE_unit_value_as_string(numstr,
|
||||||
numstr, sizeof(numstr), double(angle), angle_precision, B_UNIT_ROTATION, unit, false);
|
sizeof(numstr),
|
||||||
|
double(angle),
|
||||||
|
angle_precision,
|
||||||
|
B_UNIT_ROTATION,
|
||||||
|
unit,
|
||||||
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLF_enable(blf_mono_font, BLF_ROTATION);
|
BLF_enable(blf_mono_font, BLF_ROTATION);
|
||||||
|
|
|
@ -338,6 +338,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion * /*region*/, void *
|
||||||
-3,
|
-3,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
unit,
|
unit,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
strdrawlen = BLI_strlen_utf8(str);
|
strdrawlen = BLI_strlen_utf8(str);
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ static void ruler_item_as_string(
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BKE_unit_value_as_string(
|
BKE_unit_value_as_string(
|
||||||
numstr, numstr_size, double(ruler_angle), prec, B_UNIT_ROTATION, unit, false);
|
numstr, numstr_size, double(ruler_angle), prec, B_UNIT_ROTATION, unit, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -229,7 +229,8 @@ static void ruler_item_as_string(
|
||||||
prec,
|
prec,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
unit,
|
unit,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,7 @@ static void applyShrinkFatten(TransInfo *t)
|
||||||
4,
|
4,
|
||||||
B_UNIT_LENGTH,
|
B_UNIT_LENGTH,
|
||||||
unit,
|
unit,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -191,7 +191,7 @@ static void translate_dist_to_str(char *r_str,
|
||||||
{
|
{
|
||||||
if (unit) {
|
if (unit) {
|
||||||
BKE_unit_value_as_string(
|
BKE_unit_value_as_string(
|
||||||
r_str, r_str_maxncpy, val * unit->scale_length, 4, B_UNIT_LENGTH, unit, false);
|
r_str, r_str_maxncpy, val * unit->scale_length, 4, B_UNIT_LENGTH, unit, false, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Check range to prevent string buffer overflow. */
|
/* Check range to prevent string buffer overflow. */
|
||||||
|
|
|
@ -130,7 +130,8 @@ void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
|
||||||
n->unit_sys,
|
n->unit_sys,
|
||||||
n->unit_type[i],
|
n->unit_type[i],
|
||||||
true,
|
true,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* +1 because of trailing '\0' */
|
/* +1 because of trailing '\0' */
|
||||||
|
@ -153,7 +154,7 @@ void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
|
||||||
else {
|
else {
|
||||||
char tstr[NUM_STR_REP_LEN];
|
char tstr[NUM_STR_REP_LEN];
|
||||||
BKE_unit_value_as_string_adaptive(
|
BKE_unit_value_as_string_adaptive(
|
||||||
tstr, ln, double(n->val[i]), prec, n->unit_sys, n->unit_type[i], true, false);
|
tstr, ln, double(n->val[i]), prec, n->unit_sys, n->unit_type[i], true, false, true);
|
||||||
BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur);
|
BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +244,8 @@ static void value_to_editstr(NumInput *n, int idx)
|
||||||
n->unit_sys,
|
n->unit_sys,
|
||||||
n->unit_type[idx],
|
n->unit_type[idx],
|
||||||
true,
|
true,
|
||||||
false);
|
false,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len)
|
static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len)
|
||||||
|
|
|
@ -311,7 +311,7 @@ static PyObject *bpyunits_to_string(PyObject * /*self*/, PyObject *args, PyObjec
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
BKE_unit_value_as_string_adaptive(
|
BKE_unit_value_as_string_adaptive(
|
||||||
buf1, sizeof(buf1), value, precision, usys, ucat, bool(split_unit), false);
|
buf1, sizeof(buf1), value, precision, usys, ucat, bool(split_unit), false, true);
|
||||||
|
|
||||||
if (compatible_unit) {
|
if (compatible_unit) {
|
||||||
BKE_unit_name_to_alt(buf2, sizeof(buf2), buf1, usys, ucat);
|
BKE_unit_name_to_alt(buf2, sizeof(buf2), buf1, usys, ucat);
|
||||||
|
|
Loading…
Reference in New Issue