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/editors/interface')
-rw-r--r--source/blender/editors/interface/interface.c57
-rw-r--r--source/blender/editors/interface/interface_context_menu.c10
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c11
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c105
-rw-r--r--source/blender/editors/interface/interface_handlers.c355
-rw-r--r--source/blender/editors/interface/interface_icons.c14
-rw-r--r--source/blender/editors/interface/interface_intern.h100
-rw-r--r--source/blender/editors/interface/interface_layout.c8
-rw-r--r--source/blender/editors/interface/interface_ops.c224
-rw-r--r--source/blender/editors/interface/interface_panel.c22
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c13
-rw-r--r--source/blender/editors/interface/interface_region_search.c3
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c25
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c12
-rw-r--r--source/blender/editors/interface/interface_template_search_operator.c1
-rw-r--r--source/blender/editors/interface/interface_templates.c14
-rw-r--r--source/blender/editors/interface/interface_widgets.c101
-rw-r--r--source/blender/editors/interface/view2d_ops.c2
18 files changed, 682 insertions, 395 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 279239fcc65..26ea5f8e24a 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -52,6 +52,7 @@
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
+#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
@@ -1038,7 +1039,6 @@ static bool ui_but_is_rna_undo(const uiBut *but)
if (ID_CHECK_UNDO(id) == false) {
return false;
}
- return true;
}
if (but->rnapoin.type && !RNA_struct_undo_check(but->rnapoin.type)) {
return false;
@@ -1817,9 +1817,9 @@ static void ui_but_validate(const uiBut *but)
#endif
/**
- * Check if the operator \a ot poll is successfull with the context given by \a but (optionally).
+ * Check if the operator \a ot poll is successful with the context given by \a but (optionally).
* \param but: The button that might store context. Can be NULL for convenience (e.g. if there is
- * no button to take context from, but we still want to poll the operator).
+ * no button to take context from, but we still want to poll the operator).
*/
bool ui_but_context_poll_operator(bContext *C, wmOperatorType *ot, const uiBut *but)
{
@@ -2327,6 +2327,14 @@ bool ui_but_is_float(const uiBut *but)
return false;
}
+PropertyScaleType ui_but_scale_type(const uiBut *but)
+{
+ if (but->rnaprop) {
+ return RNA_property_ui_scale(but->rnaprop);
+ }
+ return PROP_SCALE_LINEAR;
+}
+
bool ui_but_is_bool(const uiBut *but)
{
if (ELEM(but->type,
@@ -2913,7 +2921,14 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
static bool ui_number_from_string_units(
bContext *C, const char *str, const int unit_type, const UnitSettings *unit, double *r_value)
{
- return user_string_to_number(C, str, unit, unit_type, UI_NUMBER_EVAL_ERROR_PREFIX, r_value);
+ char *error = NULL;
+ const bool ok = user_string_to_number(C, str, unit, unit_type, r_value, true, &error);
+ if (error) {
+ ReportList *reports = CTX_wm_reports(C);
+ BKE_reportf(reports, RPT_ERROR, "%s: %s", UI_NUMBER_EVAL_ERROR_PREFIX, error);
+ MEM_freeN(error);
+ }
+ return ok;
}
static bool ui_number_from_string_units_with_but(bContext *C,
@@ -2930,7 +2945,11 @@ static bool ui_number_from_string(bContext *C, const char *str, double *r_value)
{
bool ok;
#ifdef WITH_PYTHON
- ok = BPY_run_string_as_number(C, NULL, str, UI_NUMBER_EVAL_ERROR_PREFIX, r_value);
+ struct BPy_RunErrInfo err_info = {
+ .reports = CTX_wm_reports(C),
+ .report_prefix = UI_NUMBER_EVAL_ERROR_PREFIX,
+ };
+ ok = BPY_run_string_as_number(C, NULL, str, &err_info, r_value);
#else
UNUSED_VARS(C);
*r_value = atof(str);
@@ -3188,19 +3207,17 @@ void ui_but_range_set_hard(uiBut *but)
const PropertyType type = RNA_property_type(but->rnaprop);
- /* clamp button range to something reasonable in case
- * we get -inf/inf from RNA properties */
if (type == PROP_INT) {
int imin, imax;
RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax);
- but->hardmin = (imin == INT_MIN) ? -1e4 : imin;
- but->hardmax = (imin == INT_MAX) ? 1e4 : imax;
+ but->hardmin = imin;
+ but->hardmax = imax;
}
else if (type == PROP_FLOAT) {
float fmin, fmax;
RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax);
- but->hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
- but->hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax;
+ but->hardmin = fmin;
+ but->hardmax = fmax;
}
}
@@ -6127,6 +6144,7 @@ void UI_but_drag_set_asset(uiBut *but,
const char *name,
const char *path,
int id_type,
+ int import_type,
int icon,
struct ImBuf *imb,
float scale)
@@ -6136,6 +6154,7 @@ void UI_but_drag_set_asset(uiBut *but,
BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name));
asset_drag->path = path;
asset_drag->id_type = id_type;
+ asset_drag->import_type = import_type;
but->dragtype = WM_DRAG_ASSET;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
@@ -6591,6 +6610,8 @@ uiBut *uiDefSearchBut(uiBlock *block,
* \param search_create_fn: Function to create the menu.
* \param search_update_fn: Function to refresh search content after the search text has changed.
* \param arg: user value.
+ * \param free_arg: Set to true if the argument is newly allocated memory for every redraw and
+ * should be freed when the button is destroyed.
* \param search_arg_free_fn: When non-null, use this function to free \a arg.
* \param search_exec_fn: Function that executes the action, gets \a arg as the first argument.
* The second argument as the active item-pointer
@@ -6601,6 +6622,7 @@ void UI_but_func_search_set(uiBut *but,
uiButSearchCreateFn search_create_fn,
uiButSearchUpdateFn search_update_fn,
void *arg,
+ const bool free_arg,
uiButSearchArgFreeFn search_arg_free_fn,
uiButHandleFunc search_exec_fn,
void *active)
@@ -6636,11 +6658,17 @@ void UI_but_func_search_set(uiBut *but,
}
#endif
/* Handling will pass the active item as arg2 later, so keep it NULL here. */
- UI_but_func_set(but, search_exec_fn, search_but->arg, NULL);
+ if (free_arg) {
+ UI_but_funcN_set(but, search_exec_fn, search_but->arg, NULL);
+ }
+ else {
+ UI_but_func_set(but, search_exec_fn, search_but->arg, NULL);
+ }
}
- /* search buttons show red-alert if item doesn't exist, not for menus */
- if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
+ /* search buttons show red-alert if item doesn't exist, not for menus. Don't do this for
+ * buttons where any result is valid anyway, since any string will be valid anyway. */
+ if (0 == (but->block->flag & UI_BLOCK_LOOP) && !search_but->results_are_suggestions) {
/* skip empty buttons, not all buttons need input, we only show invalid */
if (but->drawstr[0]) {
ui_but_search_refresh(search_but);
@@ -6780,6 +6808,7 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
ui_searchbox_create_generic,
operator_enum_search_update_fn,
but,
+ false,
NULL,
operator_enum_search_exec_fn,
NULL);
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 91c19ff2850..b142e383df0 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -399,7 +399,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
"'%s').label",
idname);
char *expr_result = NULL;
- if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
+ if (BPY_run_string_as_string(C, expr_imports, expr, NULL, &expr_result)) {
STRNCPY(drawstr, expr_result);
MEM_freeN(expr_result);
}
@@ -542,9 +542,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
const PropertyType type = RNA_property_type(prop);
const PropertySubType subtype = RNA_property_subtype(prop);
bool is_anim = RNA_property_animateable(ptr, prop);
- const bool is_editable = RNA_property_editable(ptr, prop);
const bool is_idprop = RNA_property_is_idprop(prop);
- const bool is_set = RNA_property_is_set(ptr, prop);
/* second slower test,
* saved people finding keyframe items in menus when its not possible */
@@ -893,12 +891,6 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
"all",
1);
}
- if (is_editable /*&& is_idprop*/ && is_set) {
- uiItemO(layout,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
- ICON_NONE,
- "UI_OT_unset_property_button");
- }
if (is_idprop && !is_array && ELEM(type, PROP_INT, PROP_FLOAT)) {
uiItemO(layout,
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 178f663ff58..b52bfc81b7a 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -130,14 +130,19 @@ void eyedropper_draw_cursor_text_region(const struct bContext *C,
const char *name)
{
wmWindow *win = CTX_wm_window(C);
- const int x = win->eventstate->x - region->winrct.xmin;
- const int y = win->eventstate->y - region->winrct.ymin;
+ const int x = win->eventstate->x;
+ const int y = win->eventstate->y;
if ((name[0] == '\0') || (BLI_rcti_isect_pt(&region->winrct, x, y) == false)) {
return;
}
- eyedropper_draw_cursor_text_ex(x, y, name);
+ const int mval[2] = {
+ x - region->winrct.xmin,
+ y - region->winrct.ymin,
+ };
+
+ eyedropper_draw_cursor_text_ex(mval[0], mval[1], name);
}
/**
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 4ae6f66281f..ba72cecc514 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -116,14 +116,12 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
float col[4];
RNA_property_float_get_array(&eye->ptr, eye->prop, col);
- if (ELEM(eye->ptr.type, &RNA_CompositorNodeCryptomatteV2, &RNA_CompositorNodeCryptomatte)) {
+ if (eye->ptr.type == &RNA_CompositorNodeCryptomatteV2) {
eye->crypto_node = (bNode *)eye->ptr.data;
- eye->cryptomatte_session = ntreeCompositCryptomatteSession(eye->crypto_node);
+ eye->cryptomatte_session = ntreeCompositCryptomatteSession(CTX_data_scene(C),
+ eye->crypto_node);
eye->draw_handle_sample_text = WM_draw_cb_activate(CTX_wm_window(C), eyedropper_draw_cb, eye);
}
- else {
- eye->crypto_node = NULL;
- }
if (prop_subtype != PROP_COLOR) {
Scene *scene = CTX_data_scene(C);
@@ -202,6 +200,57 @@ static bool eyedropper_cryptomatte_sample_renderlayer_fl(RenderLayer *render_lay
return false;
}
+static bool eyedropper_cryptomatte_sample_render_fl(const bNode *node,
+ const char *prefix,
+ const float fpos[2],
+ float r_col[3])
+{
+ bool success = false;
+ Scene *scene = (Scene *)node->id;
+ BLI_assert(GS(scene->id.name) == ID_SCE);
+ Render *re = RE_GetSceneRender(scene);
+
+ if (re) {
+ RenderResult *rr = RE_AcquireResultRead(re);
+ if (rr) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name);
+ success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col);
+ if (success) {
+ break;
+ }
+ }
+ }
+ RE_ReleaseResult(re);
+ }
+ return success;
+}
+
+static bool eyedropper_cryptomatte_sample_image_fl(const bNode *node,
+ NodeCryptomatte *crypto,
+ const char *prefix,
+ const float fpos[2],
+ float r_col[3])
+{
+ bool success = false;
+ Image *image = (Image *)node->id;
+ BLI_assert((image == NULL) || (GS(image->id.name) == ID_IM));
+ ImageUser *iuser = &crypto->iuser;
+
+ if (image && image->type == IMA_TYPE_MULTILAYER) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
+ if (image->rr) {
+ LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
+ success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col);
+ if (success) {
+ break;
+ }
+ }
+ }
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ return success;
+}
static bool eyedropper_cryptomatte_sample_fl(
bContext *C, Eyedropper *eye, int mx, int my, float r_col[3])
@@ -258,53 +307,19 @@ static bool eyedropper_cryptomatte_sample_fl(
return false;
}
- bool success = false;
/* TODO(jbakker): Migrate this file to cc and use std::string as return param. */
char prefix[MAX_NAME + 1];
- ntreeCompositCryptomatteLayerPrefix(node, prefix, sizeof(prefix) - 1);
+ const Scene *scene = CTX_data_scene(C);
+ ntreeCompositCryptomatteLayerPrefix(scene, node, prefix, sizeof(prefix) - 1);
prefix[MAX_NAME] = '\0';
if (node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER) {
- Scene *scene = (Scene *)node->id;
- BLI_assert(GS(scene->id.name) == ID_SCE);
- Render *re = RE_GetSceneRender(scene);
-
- if (re) {
- RenderResult *rr = RE_AcquireResultRead(re);
- if (rr) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name);
- success = eyedropper_cryptomatte_sample_renderlayer_fl(
- render_layer, prefix, fpos, r_col);
- if (success) {
- break;
- }
- }
- }
- RE_ReleaseResult(re);
- }
+ return eyedropper_cryptomatte_sample_render_fl(node, prefix, fpos, r_col);
}
- else if (node->custom1 == CMP_CRYPTOMATTE_SRC_IMAGE) {
- Image *image = (Image *)node->id;
- BLI_assert(GS(image->id.name) == ID_IM);
- ImageUser *iuser = &crypto->iuser;
-
- if (image && image->type == IMA_TYPE_MULTILAYER) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
- if (image->rr) {
- LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
- success = eyedropper_cryptomatte_sample_renderlayer_fl(
- render_layer, prefix, fpos, r_col);
- if (success) {
- break;
- }
- }
- }
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
+ if (node->custom1 == CMP_CRYPTOMATTE_SRC_IMAGE) {
+ return eyedropper_cryptomatte_sample_image_fl(node, crypto, prefix, fpos, r_col);
}
-
- return success;
+ return false;
}
/**
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a5a5a69728e..5f98a501bec 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -126,6 +126,24 @@
#define UI_MAX_PASSWORD_STR 128
/**
+ * This is a lower limit on the soft minimum of the range.
+ * Usually the derived lower limit from the visible precision is higher,
+ * so this number is the backup minimum.
+ *
+ * Logarithmic scale does not work with a minimum value of zero,
+ * but we want to support it anyway. It is set to 0.5e... for
+ * correct rounding since when the tweaked value is lower than
+ * the log minimum (lower limit), it will snap to 0.
+ */
+#define UI_PROP_SCALE_LOG_MIN 0.5e-8f
+/**
+ * This constant defines an offset for the precision change in
+ * snap rounding, when going to higher values. It is set to
+ * `0.5 - log10(3) = 0.03` to make the switch at `0.3` values.
+ */
+#define UI_PROP_SCALE_LOG_SNAP_OFFSET 0.03f
+
+/**
* When #USER_CONTINUOUS_MOUSE is disabled or tablet input is used,
* Use this as a maximum soft range for mapping cursor motion to the value.
* Otherwise min/max of #FLT_MAX, #INT_MAX cause small adjustments to jump to large numbers.
@@ -477,6 +495,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
static void ui_do_but_extra_operator_icons_mousemove(uiBut *but,
uiHandleButtonData *data,
const wmEvent *event);
+static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data);
#ifdef USE_DRAG_MULTINUM
static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block);
@@ -1114,6 +1133,13 @@ static void ui_apply_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if (data->str) {
+ double value;
+ /* Check if the string value is a number and cancel if it's equal to the startvalue. */
+ if (ui_but_string_eval_number(C, but, data->str, &value) && (value == data->startvalue)) {
+ data->cancel = true;
+ return;
+ }
+
if (ui_but_string_set(C, but, data->str)) {
data->value = ui_but_value_get(but);
}
@@ -2320,16 +2346,16 @@ static int get_but_property_array_length(uiBut *but)
}
static void ui_but_set_float_array(
- bContext *C, uiBut *but, uiHandleButtonData *data, float *values, int array_length)
+ bContext *C, uiBut *but, uiHandleButtonData *data, const float *values, const int values_len)
{
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- for (int i = 0; i < array_length; i++) {
+ for (int i = 0; i < values_len; i++) {
RNA_property_float_set_index(&but->rnapoin, but->rnaprop, i, values[i]);
}
if (data) {
if (but->type == UI_BTYPE_UNITVEC) {
- BLI_assert(array_length == 3);
+ BLI_assert(values_len == 3);
copy_v3_v3(data->vec, values);
}
else {
@@ -2340,56 +2366,39 @@ static void ui_but_set_float_array(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
-static void float_array_to_string(float *values,
- int array_length,
+static void float_array_to_string(const float *values,
+ const int values_len,
char *output,
int output_len_max)
{
- /* to avoid buffer overflow attacks; numbers are quite arbitrary */
- BLI_assert(output_len_max > 15);
- output_len_max -= 10;
-
- int current_index = 0;
- output[current_index] = '[';
- current_index++;
-
- for (int i = 0; i < array_length; i++) {
- int length = BLI_snprintf(
- output + current_index, output_len_max - current_index, "%f", values[i]);
- current_index += length;
-
- if (i < array_length - 1) {
- if (current_index < output_len_max) {
- output[current_index + 0] = ',';
- output[current_index + 1] = ' ';
- current_index += 2;
- }
- }
+ const int values_end = values_len - 1;
+ int ofs = 0;
+ output[ofs++] = '[';
+ for (int i = 0; i < values_len; i++) {
+ ofs += BLI_snprintf_rlen(
+ output + ofs, output_len_max - ofs, (i != values_end) ? "%f, " : "%f]", values[i]);
}
-
- output[current_index + 0] = ']';
- output[current_index + 1] = '\0';
}
static void ui_but_copy_numeric_array(uiBut *but, char *output, int output_len_max)
{
- const int array_length = get_but_property_array_length(but);
- float *values = alloca(array_length * sizeof(float));
+ const int values_len = get_but_property_array_length(but);
+ float *values = alloca(values_len * sizeof(float));
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, values);
- float_array_to_string(values, array_length, output, output_len_max);
+ float_array_to_string(values, values_len, output, output_len_max);
}
-static bool parse_float_array(char *text, float *values, int expected_length)
+static bool parse_float_array(char *text, float *values, int values_len_expected)
{
/* can parse max 4 floats for now */
- BLI_assert(0 <= expected_length && expected_length <= 4);
+ BLI_assert(0 <= values_len_expected && values_len_expected <= 4);
float v[5];
- const int actual_length = sscanf(
+ const int values_len_actual = sscanf(
text, "[%f, %f, %f, %f, %f]", &v[0], &v[1], &v[2], &v[3], &v[4]);
- if (actual_length == expected_length) {
- memcpy(values, v, sizeof(float) * expected_length);
+ if (values_len_actual == values_len_expected) {
+ memcpy(values, v, sizeof(float) * values_len_expected);
return true;
}
return false;
@@ -2400,16 +2409,16 @@ static void ui_but_paste_numeric_array(bContext *C,
uiHandleButtonData *data,
char *buf_paste)
{
- const int array_length = get_but_property_array_length(but);
- if (array_length > 4) {
+ const int values_len = get_but_property_array_length(but);
+ if (values_len > 4) {
/* not supported for now */
return;
}
- float *values = alloca(sizeof(float) * array_length);
+ float *values = alloca(sizeof(float) * values_len);
- if (parse_float_array(buf_paste, values, array_length)) {
- ui_but_set_float_array(C, but, data, values, array_length);
+ if (parse_float_array(buf_paste, values, values_len)) {
+ ui_but_set_float_array(C, but, data, values, values_len);
}
else {
WM_report(RPT_ERROR, "Expected an array of numbers: [n, n, ...]");
@@ -3354,6 +3363,8 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
if (is_num_but) {
BLI_assert(data->is_str_dynamic == false);
ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
+
+ ui_numedit_begin_set_values(but, data);
}
/* won't change from now on */
@@ -3890,6 +3901,14 @@ static void ui_do_but_textedit_select(
/** \name Button Number Editing (various types)
* \{ */
+static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data)
+{
+ data->startvalue = ui_but_value_get(but);
+ data->origvalue = data->startvalue;
+ data->value = data->origvalue;
+ but->editval = &data->value;
+}
+
static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
{
if (but->type == UI_BTYPE_CURVE) {
@@ -3915,19 +3934,21 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
but->editvec = data->vec;
}
else {
- float softrange, softmin, softmax;
+ ui_numedit_begin_set_values(but, data);
- data->startvalue = ui_but_value_get(but);
- data->origvalue = data->startvalue;
- data->value = data->origvalue;
- but->editval = &data->value;
+ float softmin = but->softmin;
+ float softmax = but->softmax;
+ float softrange = softmax - softmin;
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
+ float log_min = (scale_type == PROP_SCALE_LOG) ? max_ff(softmin, UI_PROP_SCALE_LOG_MIN) : 0.0f;
if ((but->type == UI_BTYPE_NUM) && (ui_but_is_cursor_warp(but) == false)) {
uiButNumber *number_but = (uiButNumber *)but;
+
+ if (scale_type == PROP_SCALE_LOG) {
+ log_min = max_ff(log_min, powf(10, -number_but->precision) * 0.5f);
+ }
/* Use a minimum so we have a predictable range,
* otherwise some float buttons get a large range. */
const float value_step_float_min = 0.1f;
@@ -3976,7 +3997,31 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
}
}
- data->dragfstart = (softrange == 0.0f) ? 0.0f : ((float)data->value - softmin) / softrange;
+ if (softrange == 0.0f) {
+ data->dragfstart = 0.0f;
+ }
+ else {
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ data->dragfstart = ((float)data->value - softmin) / softrange;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ BLI_assert(log_min != 0.0f);
+ const float base = softmax / log_min;
+ data->dragfstart = logf((float)data->value / log_min) / logf(base);
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubic_min = cube_f(softmin);
+ const float cubic_max = cube_f(softmax);
+ const float cubic_range = cubic_max - cubic_min;
+ const float f = ((float)data->value - softmin) * cubic_range / softrange + cubic_min;
+ data->dragfstart = (cbrtf(f) - softmin) / softrange;
+ break;
+ }
+ }
+ }
data->dragf = data->dragfstart;
data->drag_map_soft_min = softmin;
@@ -4694,6 +4739,7 @@ static float ui_numedit_apply_snapf(
/* pass */
}
else {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
float softrange = softmax - softmin;
float fac = 1.0f;
@@ -4731,31 +4777,30 @@ static float ui_numedit_apply_snapf(
}
}
- if (snap == SNAP_ON) {
- if (softrange < 2.10f) {
- tempf = roundf(tempf * 10.0f) * 0.1f;
- }
- else if (softrange < 21.0f) {
- tempf = roundf(tempf);
- }
- else {
- tempf = roundf(tempf * 0.1f) * 10.0f;
- }
- }
- else if (snap == SNAP_ON_SMALL) {
- if (softrange < 2.10f) {
- tempf = roundf(tempf * 100.0f) * 0.01f;
- }
- else if (softrange < 21.0f) {
- tempf = roundf(tempf * 10.0f) * 0.1f;
+ BLI_assert(ELEM(snap, SNAP_ON, SNAP_ON_SMALL));
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR:
+ case PROP_SCALE_CUBIC: {
+ const float snap_fac = (snap == SNAP_ON_SMALL ? 0.1f : 1.0f);
+ if (softrange < 2.10f) {
+ tempf = roundf(tempf * 10.0f / snap_fac) * 0.1f * snap_fac;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf / snap_fac) * snap_fac;
+ }
+ else {
+ tempf = roundf(tempf * 0.1f / snap_fac) * 10.0f * snap_fac;
+ }
+ break;
}
- else {
- tempf = roundf(tempf);
+ case PROP_SCALE_LOG: {
+ const float snap_fac = powf(10.0f,
+ roundf(log10f(tempf) + UI_PROP_SCALE_LOG_SNAP_OFFSET) -
+ (snap == SNAP_ON_SMALL ? 2.0f : 1.0f));
+ tempf = roundf(tempf / snap_fac) * snap_fac;
+ break;
}
}
- else {
- BLI_assert(0);
- }
if (fac != 1.0f) {
tempf *= fac;
@@ -4800,6 +4845,7 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
int lvalue, temp;
bool changed = false;
const bool is_float = ui_but_is_float(but);
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
/* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
if ((is_motion || data->draglock) && (ui_but_dragedit_update_mval(data, mx) == false)) {
@@ -4811,21 +4857,74 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
const float softmax = but->softmax;
const float softrange = softmax - softmin;
+ const float log_min = (scale_type == PROP_SCALE_LOG) ?
+ max_ff(max_ff(softmin, UI_PROP_SCALE_LOG_MIN),
+ powf(10, -number_but->precision) * 0.5f) :
+ 0;
+
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if (is_float) {
fac *= 0.01f * number_but->step_size;
- tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = (float)data->startvalue + (float)(mx - data->dragstartx) * fac;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float startvalue = max_ff((float)data->startvalue, log_min);
+ tempf = expf((float)(mx - data->dragstartx) * fac) * startvalue;
+ if (tempf <= log_min) {
+ tempf = 0.0f;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ tempf = cbrtf((float)data->startvalue) + (float)(mx - data->dragstartx) * fac;
+ tempf *= tempf * tempf;
+ break;
+ }
+ }
+
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, snap);
#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
- if (tempf < softmin) {
- data->dragstartx -= (softmin - tempf) / fac;
- tempf = softmin;
- }
- else if (tempf > softmax) {
- data->dragstartx += (tempf - softmax) / fac;
- tempf = softmax;
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ if (tempf < softmin) {
+ data->dragstartx -= (softmin - tempf) / fac;
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx -= (softmax - tempf) / fac;
+ tempf = softmax;
+ }
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ if (tempf < log_min) {
+ data->dragstartx -= logf(log_min / (float)data->startvalue) / fac -
+ (float)(mx - data->dragstartx);
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx -= logf(softmax / (float)data->startvalue) / fac -
+ (float)(mx - data->dragstartx);
+ tempf = softmax;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ if (tempf < softmin) {
+ data->dragstartx = mx - (int)((cbrtf(softmin) - cbrtf((float)data->startvalue)) / fac);
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx = mx - (int)((cbrtf(softmax) - cbrtf((float)data->startvalue)) / fac);
+ tempf = softmax;
+ }
+ break;
+ }
}
#else
CLAMP(tempf, softmin, softmax);
@@ -4932,7 +5031,31 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
}
data->draglastx = mx;
- tempf = (softmin + data->dragf * softrange);
+
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = (softmin + data->dragf * softrange);
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float log_min = max_ff(max_ff(softmin, UI_PROP_SCALE_LOG_MIN),
+ powf(10.0f, -number_but->precision) * 0.5f);
+ const float base = softmax / log_min;
+ tempf = powf(base, data->dragf) * log_min;
+ if (tempf <= log_min) {
+ tempf = 0.0f;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ tempf = (softmin + data->dragf * softrange);
+ tempf *= tempf * tempf;
+ float cubic_min = softmin * softmin * softmin;
+ float cubic_max = softmax * softmax * softmax;
+ tempf = (tempf - cubic_min) / (cubic_max - cubic_min) * softrange + softmin;
+ break;
+ }
+ }
if (!is_float) {
temp = round_fl_to_int(tempf);
@@ -5179,9 +5302,19 @@ static int ui_do_but_NUM(
else {
/* Float Value. */
if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- const double value_step = (double)number_but->step_size * UI_PRECISION_FLOAT_SCALE;
+ double value_step;
+ if (scale_type == PROP_SCALE_LOG) {
+ value_step = powf(10.0f,
+ (roundf(log10f(data->value) + UI_PROP_SCALE_LOG_SNAP_OFFSET) - 1.0f) +
+ log10f(number_but->step_size));
+ }
+ else {
+ value_step = (double)number_but->step_size * UI_PRECISION_FLOAT_SCALE;
+ }
BLI_assert(value_step > 0.0f);
const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ?
(double)max_ff(but->softmin,
@@ -5229,6 +5362,8 @@ static bool ui_numedit_but_SLI(uiBut *but,
return changed;
}
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
@@ -5270,7 +5405,24 @@ static bool ui_numedit_but_SLI(uiBut *but,
#endif
/* done correcting mouse */
- tempf = softmin + f * softrange;
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = softmin + f * softrange;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ tempf = powf(softmax / softmin, f) * softmin;
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubicmin = cube_f(softmin);
+ const float cubicmax = cube_f(softmax);
+ const float cubicrange = cubicmax - cubicmin;
+ tempf = cube_f(softmin + f * softrange);
+ tempf = (tempf - cubicmin) / cubicrange * softrange + softmin;
+ break;
+ }
+ }
temp = round_fl_to_int(tempf);
if (snap) {
@@ -5464,6 +5616,8 @@ static int ui_do_but_SLI(
if (click) {
if (click == 2) {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
/* nudge slider to the left or right */
float f, tempf, softmin, softmax, softrange;
int temp;
@@ -5488,14 +5642,20 @@ static int ui_do_but_SLI(
f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
}
- f = softmin + f * softrange;
+ if (scale_type == PROP_SCALE_LOG) {
+ f = powf(softmax / softmin, f) * softmin;
+ }
+ else {
+ f = softmin + f * softrange;
+ }
if (!ui_but_is_float(but)) {
+ int value_step = 1;
if (f < temp) {
- temp--;
+ temp -= value_step;
}
else {
- temp++;
+ temp += value_step;
}
if (temp >= softmin && temp <= softmax) {
@@ -5506,14 +5666,23 @@ static int ui_do_but_SLI(
}
}
else {
- if (f < tempf) {
- tempf -= 0.01f;
- }
- else {
- tempf += 0.01f;
- }
-
if (tempf >= softmin && tempf <= softmax) {
+ float value_step;
+ if (scale_type == PROP_SCALE_LOG) {
+ value_step = powf(10.0f, roundf(log10f(tempf) + UI_PROP_SCALE_LOG_SNAP_OFFSET) - 1.0f);
+ }
+ else {
+ value_step = 0.01f;
+ }
+
+ if (f < tempf) {
+ tempf -= value_step;
+ }
+ else {
+ tempf += value_step;
+ }
+
+ CLAMP(tempf, softmin, softmax);
data->value = tempf;
}
else {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c16c3d2c49a..4defbed940e 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -457,13 +457,15 @@ DEF_ICON_VECTOR_COLORSET_DRAW_NTH(20, 19)
# undef DEF_ICON_VECTOR_COLORSET_DRAW_NTH
static void vicon_collection_color_draw(
- short color_tag, int x, int y, int UNUSED(w), int UNUSED(h), float UNUSED(alpha))
+ short color_tag, int x, int y, int w, int UNUSED(h), float UNUSED(alpha))
{
bTheme *btheme = UI_GetTheme();
const ThemeCollectionColor *collection_color = &btheme->collection_color[color_tag];
+ const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
+
UI_icon_draw_ex(
- x, y, ICON_OUTLINER_COLLECTION, U.inv_dpi_fac, 1.0f, 0.0f, collection_color->color, true);
+ x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true);
}
# define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \
@@ -1426,13 +1428,7 @@ static void icon_set_image(const bContext *C,
scene = CTX_data_scene(C);
}
/* Immediate version */
- ED_preview_icon_render(CTX_data_main(C),
- CTX_data_ensure_evaluated_depsgraph(C),
- scene,
- id,
- prv_img->rect[size],
- prv_img->w[size],
- prv_img->h[size]);
+ ED_preview_icon_render(C, scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4c96512b4f3..23856c41ceb 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -62,7 +62,7 @@ struct wmTimer;
#define UI_MENU_PADDING (int)(0.2f * UI_UNIT_Y)
#define UI_MENU_WIDTH_MIN (UI_UNIT_Y * 9)
-/* some extra padding added to menus containing submenu icons */
+/** Some extra padding added to menus containing sub-menu icons. */
#define UI_MENU_SUBMENU_PADDING (6 * UI_DPI_FAC)
/* menu scrolling */
@@ -74,28 +74,31 @@ struct wmTimer;
#define UI_PANEL_MINX 100
#define UI_PANEL_MINY 70
-/* popover width (multiplied by 'U.widget_unit') */
+/** Popover width (multiplied by #U.widget_unit) */
#define UI_POPOVER_WIDTH_UNITS 10
-/* uiBut->flag */
+/** #uiBut.flag */
enum {
- UI_SELECT = (1 << 0), /* use when the button is pressed */
- UI_SCROLLED = (1 << 1), /* temp hidden, scrolled away */
+ /** Use when the button is pressed. */
+ UI_SELECT = (1 << 0),
+ /** Temporarily hidden (scrolled out of the view). */
+ UI_SCROLLED = (1 << 1),
UI_ACTIVE = (1 << 2),
UI_HAS_ICON = (1 << 3),
UI_HIDDEN = (1 << 4),
- UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
+ /** Display selected, doesn't impact interaction. */
+ UI_SELECT_DRAW = (1 << 5),
/** Property search filter is active and the button does not match. */
- UI_SEARCH_FILTER_NO_MATCH = (1 << 12),
- /* warn: rest of uiBut->flag in UI_interface.h */
+ UI_SEARCH_FILTER_NO_MATCH = (1 << 6),
+ /* WARNING: rest of #uiBut.flag in UI_interface.h */
};
-/* uiBut->dragflag */
+/** #uiBut.dragflag */
enum {
UI_BUT_DRAGPOIN_FREE = (1 << 0),
};
-/* but->pie_dir */
+/** #uiBut.pie_dir */
typedef enum RadialDirection {
UI_RADIAL_NONE = -1,
UI_RADIAL_N = 0,
@@ -126,13 +129,13 @@ extern const short ui_radial_dir_to_angle[8];
#define UI_BITBUT_ROW(min, max) \
(((max) >= 31 ? 0xFFFFFFFF : (1 << ((max) + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0))
-/* split numbuts by ':' and align l/r */
+/** Split number-buttons by ':' and align left/right. */
#define USE_NUMBUTS_LR_ALIGN
-/* Use new 'align' computation code. */
+/** Use new 'align' computation code. */
#define USE_UIBUT_SPATIAL_ALIGN
-/* PieMenuData->flags */
+/** #PieMenuData.flags */
enum {
/** pie menu item collision is detected at 90 degrees */
UI_PIE_DEGREES_RANGE_LARGE = (1 << 0),
@@ -152,13 +155,13 @@ enum {
#define PIE_CLICK_THRESHOLD_SQ 50.0f
-/* max amount of items a radial menu (pie menu) can contain */
+/** The maximum number of items a radial menu (pie menu) can contain. */
#define PIE_MAX_ITEMS 8
struct uiBut {
struct uiBut *next, *prev;
- /* Pointer back to the layout item holding this button. */
+ /** Pointer back to the layout item holding this button. */
uiLayout *layout;
int flag, drawflag;
eButType type;
@@ -235,10 +238,10 @@ struct uiBut {
short modifier_key;
short iconadd;
- /* UI_BTYPE_BLOCK data */
+ /** #UI_BTYPE_BLOCK data */
uiBlockCreateFunc block_create_func;
- /* UI_BTYPE_PULLDOWN/UI_BTYPE_MENU data */
+ /** #UI_BTYPE_PULLDOWN / #UI_BTYPE_MENU data */
uiMenuCreateFunc menu_create_func;
uiMenuStepFunc menu_step_func;
@@ -252,9 +255,11 @@ struct uiBut {
struct wmOperatorType *optype;
struct PointerRNA *opptr;
short opcontext;
- uchar menu_key; /* 'a'-'z', always lower case */
- ListBase extra_op_icons; /* uiButExtraOpIcon */
+ /** When non-zero, this is the key used to activate a menu items (`a-z` always lower case). */
+ uchar menu_key;
+
+ ListBase extra_op_icons; /** #uiButExtraOpIcon */
/* Draggable data, type is WM_DRAG_... */
char dragtype;
@@ -263,10 +268,10 @@ struct uiBut {
struct ImBuf *imb;
float imb_scale;
- /* active button data */
+ /** Active button data (set when the user is hovering or interacting with a button). */
struct uiHandleButtonData *active;
- /* Custom button data. */
+ /** Custom button data (borrowed, not owned). */
void *custom_data;
char *editstr;
@@ -429,7 +434,7 @@ struct PieMenuData {
float alphafac;
};
-/* uiBlock.content_hints */
+/** #uiBlock.content_hints */
enum eBlockContentHints {
/** In a menu block, if there is a single sub-menu button, we add some
* padding to the right to put nicely aligned triangle icons there. */
@@ -463,7 +468,8 @@ struct uiBlock {
struct Panel *panel;
uiBlock *oldblock;
- ListBase butstore; /* UI_butstore_* runtime function */
+ /** Used for `UI_butstore_*` runtime function. */
+ ListBase butstore;
ListBase button_groups; /* #uiButtonGroup. */
@@ -479,7 +485,8 @@ struct uiBlock {
rctf rect;
float aspect;
- uint puphash; /* popup menu hash for memory */
+ /** Unique hash used to implement popup menu memory. */
+ uint puphash;
uiButHandleFunc func;
void *func_arg1;
@@ -494,10 +501,10 @@ struct uiBlock {
uiBlockHandleFunc handle_func;
void *handle_func_arg;
- /* custom extra handling */
+ /** Custom extra event handling. */
int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *);
- /* extra draw function for custom blocks */
+ /** Custom extra draw function for custom blocks. */
void (*drawextra)(const struct bContext *C, void *idv, void *arg1, void *arg2, rcti *rect);
void *drawextra_arg1;
void *drawextra_arg2;
@@ -507,7 +514,7 @@ struct uiBlock {
/** Hints about the buttons of this block. Used to avoid iterating over
* buttons to find out if some criteria is met by any. Instead, check this
* criteria when adding the button and set a flag here if it's met. */
- short content_hints; /* eBlockContentHints */
+ short content_hints; /* #eBlockContentHints */
char direction;
/** UI_BLOCK_THEME_STYLE_* */
@@ -521,11 +528,11 @@ struct uiBlock {
const char *lockstr;
bool lock;
- /** to keep blocks while drawing and free them afterwards */
+ /** To keep blocks while drawing and free them afterwards. */
bool active;
- /** to avoid tooltip after click */
+ /** To avoid tool-tip after click. */
bool tooltipdisabled;
- /** UI_block_end done? */
+ /** True when #UI_block_end has been called. */
bool endblock;
/** for doing delayed */
@@ -535,12 +542,12 @@ struct uiBlock {
/** for doing delayed */
int bounds, minbounds;
- /** pull-downs, to detect outside, can differ per case how it is created. */
+ /** Pull-downs, to detect outside, can differ per case how it is created. */
rctf safety;
- /** uiSafetyRct list */
+ /** #uiSafetyRct list */
ListBase saferct;
- uiPopupBlockHandle *handle; /* handle */
+ uiPopupBlockHandle *handle;
/** use so presets can find the operator,
* across menus and from nested popups which fail for operator context. */
@@ -555,10 +562,12 @@ struct uiBlock {
/** \note only accessed by color picker templates. */
ColorPickerData color_pickers;
- bool is_color_gamma_picker; /* Block for color picker with gamma baked in. */
+ /** Block for color picker with gamma baked in. */
+ bool is_color_gamma_picker;
- /** display device name used to display this block,
- * used by color widgets to transform colors from/to scene linear
+ /**
+ * Display device name used to display this block,
+ * used by color widgets to transform colors from/to scene linear.
*/
char display_device[64];
@@ -651,6 +660,7 @@ bool ui_but_context_poll_operator(struct bContext *C, struct wmOperatorType *ot,
extern void ui_but_update(uiBut *but);
extern void ui_but_update_edited(uiBut *but);
+extern PropertyScaleType ui_but_scale_type(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_float(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
@@ -671,9 +681,9 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
/* interface_regions.c */
struct uiKeyNavLock {
- /* Set when we're using key-input. */
+ /** Set when we're using keyboard-input. */
bool is_keynav;
- /* only used to check if we've moved the cursor */
+ /** Only used to check if we've moved the cursor. */
int event_xy[2];
};
@@ -689,7 +699,7 @@ struct uiPopupBlockCreate {
int event_xy[2];
- /* when popup is initialized from a button */
+ /** Set when popup is initialized from a button. */
struct ARegion *butregion;
uiBut *but;
};
@@ -698,7 +708,7 @@ struct uiPopupBlockHandle {
/* internal */
struct ARegion *region;
- /* use only for 'UI_BLOCK_MOVEMOUSE_QUIT' popups */
+ /** Use only for #UI_BLOCK_MOVEMOUSE_QUIT popups. */
float towards_xy[2];
double towardstime;
bool dotowards;
@@ -708,9 +718,9 @@ struct uiPopupBlockHandle {
void (*cancel_func)(struct bContext *C, void *arg);
void *popup_arg;
- /* store data for refreshing popups */
+ /** Store data for refreshing popups. */
struct uiPopupBlockCreate popup_create_vars;
- /* true if we can re-create the popup using 'popup_create_vars' */
+ /** True if we can re-create the popup using #uiPopupBlockHandle.popup_create_vars. */
bool can_refresh;
bool refresh;
@@ -730,7 +740,7 @@ struct uiPopupBlockHandle {
int retvalue;
float retvec[4];
- /* menu direction */
+ /** Menu direction. */
int direction;
/* Previous values so we don't resize or reposition on refresh. */
@@ -924,9 +934,7 @@ extern void ui_but_execute_end(struct bContext *C,
void *active_back);
extern void ui_but_active_free(const struct bContext *C, uiBut *but);
extern int ui_but_menu_direction(uiBut *but);
-extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR],
- uiBut *but,
- const bool restore);
+extern void ui_but_text_password_hide(char password_str[128], uiBut *but, const bool restore);
extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
bool ui_but_is_editing(const uiBut *but);
float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 4430d00f2e3..c04432a2912 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2718,6 +2718,7 @@ uiBut *ui_but_add_search(
ui_searchbox_create_generic,
ui_rna_collection_search_update_fn,
coll_search,
+ false,
ui_rna_collection_search_arg_free_fn,
NULL,
NULL);
@@ -3037,7 +3038,7 @@ void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, i
/* popover */
void uiItemPopoverPanel_ptr(
- uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
+ uiLayout *layout, const bContext *C, PanelType *pt, const char *name, int icon)
{
if (!name) {
name = CTX_IFACE_(pt->translation_context, pt->label);
@@ -3066,7 +3067,7 @@ void uiItemPopoverPanel_ptr(
}
void uiItemPopoverPanel(
- uiLayout *layout, bContext *C, const char *panel_type, const char *name, int icon)
+ uiLayout *layout, const bContext *C, const char *panel_type, const char *name, int icon)
{
PanelType *pt = WM_paneltype_find(panel_type, true);
if (pt == NULL) {
@@ -4041,12 +4042,11 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
int emy = 0;
int miny = 0;
- int w = litem->w - (flow->totcol - 1) * style->columnspace;
emh = toth / flow->totcol;
/* create column per column */
col = 0;
- w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol;
+ int w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 540e98f542e..0cf3ad59903 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -72,6 +72,7 @@
#include "BKE_main.h"
#include "BLI_ghash.h"
#include "ED_screen.h"
+#include "ED_text.h"
/* -------------------------------------------------------------------- */
/** \name Copy Data Path Operator
@@ -1336,18 +1337,23 @@ static int editsource_text_edit(bContext *C,
return OPERATOR_CANCELLED;
}
+ txt_move_toline(text, line - 1, false);
+
/* naughty!, find text area to set, not good behavior
* but since this is a dev tool lets allow it - campbell */
ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
if (area) {
SpaceText *st = area->spacedata.first;
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
st->text = text;
+ if (region) {
+ ED_text_scroll_to_cursor(st, region, true);
+ }
}
else {
BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2);
}
- txt_move_toline(text, line - 1, false);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
return OPERATOR_FINISHED;
@@ -1374,7 +1380,9 @@ static int editsource_exec(bContext *C, wmOperator *op)
/* redraw and get active button python info */
ED_region_do_layout(C, region);
+ WM_draw_region_viewport_bind(region);
ED_region_do_draw(C, region);
+ WM_draw_region_viewport_unbind(region);
region->do_draw = false;
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
@@ -1487,117 +1495,115 @@ static void edittranslation_find_po_file(const char *root,
static int edittranslation_exec(bContext *C, wmOperator *op)
{
uiBut *but = UI_context_active_but_get(C);
- int ret = OPERATOR_CANCELLED;
-
- if (but) {
- wmOperatorType *ot;
- PointerRNA ptr;
- char popath[FILE_MAX];
- const char *root = U.i18ndir;
- const char *uilng = BLT_lang_get();
-
- uiStringInfo but_label = {BUT_GET_LABEL, NULL};
- uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
- uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
- uiStringInfo but_tip = {BUT_GET_TIP, NULL};
- uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
- uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
- uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
- uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
- uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
- uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
-
- if (!BLI_is_dir(root)) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Please set your Preferences' 'Translation Branches "
- "Directory' path to a valid directory");
- return OPERATOR_CANCELLED;
- }
- ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
- if (ot == NULL) {
- BKE_reportf(op->reports,
- RPT_ERROR,
- "Could not find operator '%s'! Please enable ui_translate add-on "
- "in the User Preferences",
- EDTSRC_I18N_OP_NAME);
- return OPERATOR_CANCELLED;
- }
- /* Try to find a valid po file for current language... */
- edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
- /* printf("po path: %s\n", popath); */
- if (popath[0] == '\0') {
- BKE_reportf(
- op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
- return OPERATOR_CANCELLED;
- }
-
- UI_but_string_info_get(C,
- but,
- &but_label,
- &rna_label,
- &enum_label,
- &but_tip,
- &rna_tip,
- &enum_tip,
- &rna_struct,
- &rna_prop,
- &rna_enum,
- &rna_ctxt,
- NULL);
-
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "lang", uilng);
- RNA_string_set(&ptr, "po_file", popath);
- RNA_string_set(&ptr, "but_label", but_label.strinfo);
- RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
- RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
- RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
- RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
- RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
- RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
- RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
- RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
- RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
-
- /* Clean up */
- if (but_label.strinfo) {
- MEM_freeN(but_label.strinfo);
- }
- if (rna_label.strinfo) {
- MEM_freeN(rna_label.strinfo);
- }
- if (enum_label.strinfo) {
- MEM_freeN(enum_label.strinfo);
- }
- if (but_tip.strinfo) {
- MEM_freeN(but_tip.strinfo);
- }
- if (rna_tip.strinfo) {
- MEM_freeN(rna_tip.strinfo);
- }
- if (enum_tip.strinfo) {
- MEM_freeN(enum_tip.strinfo);
- }
- if (rna_struct.strinfo) {
- MEM_freeN(rna_struct.strinfo);
- }
- if (rna_prop.strinfo) {
- MEM_freeN(rna_prop.strinfo);
- }
- if (rna_enum.strinfo) {
- MEM_freeN(rna_enum.strinfo);
- }
- if (rna_ctxt.strinfo) {
- MEM_freeN(rna_ctxt.strinfo);
- }
+ if (but == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Active button not found");
+ return OPERATOR_CANCELLED;
+ }
- return ret;
+ wmOperatorType *ot;
+ PointerRNA ptr;
+ char popath[FILE_MAX];
+ const char *root = U.i18ndir;
+ const char *uilng = BLT_lang_get();
+
+ uiStringInfo but_label = {BUT_GET_LABEL, NULL};
+ uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
+ uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
+ uiStringInfo but_tip = {BUT_GET_TIP, NULL};
+ uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
+ uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
+ uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
+ uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
+ uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
+ uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
+
+ if (!BLI_is_dir(root)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Please set your Preferences' 'Translation Branches "
+ "Directory' path to a valid directory");
+ return OPERATOR_CANCELLED;
+ }
+ ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
+ if (ot == NULL) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not find operator '%s'! Please enable ui_translate add-on "
+ "in the User Preferences",
+ EDTSRC_I18N_OP_NAME);
+ return OPERATOR_CANCELLED;
+ }
+ /* Try to find a valid po file for current language... */
+ edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
+ /* printf("po path: %s\n", popath); */
+ if (popath[0] == '\0') {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
+ return OPERATOR_CANCELLED;
}
- BKE_report(op->reports, RPT_ERROR, "Active button not found");
- return OPERATOR_CANCELLED;
+ UI_but_string_info_get(C,
+ but,
+ &but_label,
+ &rna_label,
+ &enum_label,
+ &but_tip,
+ &rna_tip,
+ &enum_tip,
+ &rna_struct,
+ &rna_prop,
+ &rna_enum,
+ &rna_ctxt,
+ NULL);
+
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_string_set(&ptr, "lang", uilng);
+ RNA_string_set(&ptr, "po_file", popath);
+ RNA_string_set(&ptr, "but_label", but_label.strinfo);
+ RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
+ RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
+ RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
+ RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
+ RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
+ RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
+ RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
+ RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
+ RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
+ const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+
+ /* Clean up */
+ if (but_label.strinfo) {
+ MEM_freeN(but_label.strinfo);
+ }
+ if (rna_label.strinfo) {
+ MEM_freeN(rna_label.strinfo);
+ }
+ if (enum_label.strinfo) {
+ MEM_freeN(enum_label.strinfo);
+ }
+ if (but_tip.strinfo) {
+ MEM_freeN(but_tip.strinfo);
+ }
+ if (rna_tip.strinfo) {
+ MEM_freeN(rna_tip.strinfo);
+ }
+ if (enum_tip.strinfo) {
+ MEM_freeN(enum_tip.strinfo);
+ }
+ if (rna_struct.strinfo) {
+ MEM_freeN(rna_struct.strinfo);
+ }
+ if (rna_prop.strinfo) {
+ MEM_freeN(rna_prop.strinfo);
+ }
+ if (rna_enum.strinfo) {
+ MEM_freeN(rna_enum.strinfo);
+ }
+ if (rna_ctxt.strinfo) {
+ MEM_freeN(rna_ctxt.strinfo);
+ }
+
+ return ret;
}
static void UI_OT_edittranslation_init(wmOperatorType *ot)
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 7343417137a..6505a7cd76a 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -437,15 +437,21 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr
/* Find how many instanced panels with this context string. */
int list_panels_len = 0;
+ int start_index = -1;
LISTBASE_FOREACH (const Panel *, panel, &region->panels) {
if (panel->type) {
if (panel->type->flag & PANEL_TYPE_INSTANCED) {
if (panel_type_context_poll(region, panel->type, context)) {
+ if (panel == drag_panel) {
+ BLI_assert(start_index == -1); /* This panel should only appear once. */
+ start_index = list_panels_len;
+ }
list_panels_len++;
}
}
}
}
+ BLI_assert(start_index != -1); /* The drag panel should definitely be in the list. */
/* Sort the matching instanced panels by their display order. */
PanelSort *panel_sort = MEM_callocN(list_panels_len * sizeof(*panel_sort), __func__);
@@ -472,6 +478,11 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr
MEM_freeN(panel_sort);
+ if (move_to_index == start_index) {
+ /* In this case, the reorder was not changed, so don't do any updates or call the callback. */
+ return;
+ }
+
/* Set the bit to tell the interface to instanced the list. */
drag_panel->flag |= PNL_INSTANCED_LIST_ORDER_CHANGED;
@@ -2529,9 +2540,8 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm
{
ARegion *region = CTX_wm_region(C);
- Panel *panel = NULL;
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
- panel = block->panel;
+ Panel *panel = block->panel;
if (panel == NULL) {
continue;
}
@@ -2541,15 +2551,11 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm
ui_window_to_block(region, block, &mx, &my);
const int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my);
if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
- break;
+ return UI_panel_custom_data_get(panel);
}
}
- if (panel == NULL) {
- return NULL;
- }
-
- return UI_panel_custom_data_get(panel);
+ return NULL;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index f234f0fbbf5..58a74a3473e 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -86,6 +86,17 @@ int ui_but_menu_step(uiBut *but, int direction)
return 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Popup Menu Memory
+ *
+ * Support menu-memory, a feature that positions the cursor
+ * over the previously used menu item.
+ *
+ * \note This is stored for each unique menu title.
+ * \{ */
+
static uint ui_popup_string_hash(const char *str, const bool use_sep)
{
/* sometimes button contains hotkey, sometimes not, strip for proper compare */
@@ -392,7 +403,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
pup->layout = UI_block_layout(
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
- /* note, this intentionally differs from the menu & submenu default because many operators
+ /* note, this intentionally differs from the menu & sub-menu default because many operators
* use popups like this to select one of their options -
* where having invoke doesn't make sense */
uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 12044863b8c..987cde61f97 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -677,8 +677,7 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
}
/* The previous menu item draws the active selection. */
- ui_draw_menu_item(
- &data->fstyle, &rect, name_sep, icon, state & ~UI_ACTIVE, separator_type, NULL);
+ ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, NULL);
}
}
/* indicate more */
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 244cf7622e0..accfb78ab94 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -428,7 +428,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
if (has_valid_context == false) {
expr_result = BLI_strdup(has_valid_context_error);
}
- else if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
+ else if (BPY_run_string_as_string(C, expr_imports, expr, NULL, &expr_result)) {
if (STREQ(expr_result, "")) {
MEM_freeN(expr_result);
expr_result = NULL;
@@ -485,7 +485,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
if (has_valid_context == false) {
expr_result = BLI_strdup(has_valid_context_error);
}
- else if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
+ else if (BPY_run_string_as_string(C, expr_imports, expr, NULL, &expr_result)) {
if (STREQ(expr_result, ".")) {
MEM_freeN(expr_result);
expr_result = NULL;
@@ -589,7 +589,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
if (has_valid_context == false) {
shortcut = BLI_strdup(has_valid_context_error);
}
- else if (BPY_run_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
+ else if (BPY_run_string_as_intptr(C, expr_imports, expr, NULL, &expr_result)) {
if (expr_result != 0) {
wmKeyMap *keymap = (wmKeyMap *)expr_result;
LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
@@ -654,7 +654,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
/* pass */
}
else if (BPY_run_string_as_string_and_size(
- C, expr_imports, expr, __func__, &expr_result, &expr_result_len)) {
+ C, expr_imports, expr, NULL, &expr_result, &expr_result_len)) {
/* pass. */
}
}
@@ -731,7 +731,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
if (has_valid_context == false) {
/* pass */
}
- else if (BPY_run_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
+ else if (BPY_run_string_as_intptr(C, expr_imports, expr, NULL, &expr_result)) {
if (expr_result != 0) {
{
uiTooltipField *field = text_field_add(data,
@@ -947,12 +947,13 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
/* button is disabled, we may be able to tell user why */
if (but->flag & UI_BUT_DISABLED) {
const char *disabled_msg = NULL;
+ bool disabled_msg_free = false;
/* if operator poll check failed, it can give pretty precise info why */
if (but->optype) {
- CTX_wm_operator_poll_msg_set(C, NULL);
+ CTX_wm_operator_poll_msg_clear(C);
WM_operator_poll_context(C, but->optype, but->opcontext);
- disabled_msg = CTX_wm_operator_poll_msg_get(C);
+ disabled_msg = CTX_wm_operator_poll_msg_get(C, &disabled_msg_free);
}
/* alternatively, buttons can store some reasoning too */
else if (but->disabled_info) {
@@ -967,6 +968,9 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
});
field->text = BLI_sprintfN(TIP_("Disabled: %s"), disabled_msg);
}
+ if (disabled_msg_free) {
+ MEM_freeN((void *)disabled_msg);
+ }
}
if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
@@ -1469,9 +1473,10 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
*/
if (gz->type->screen_bounds_get) {
rcti bounds;
- gz->type->screen_bounds_get(C, gz, &bounds);
- init_position[0] = bounds.xmin;
- init_position[1] = bounds.ymin;
+ if (gz->type->screen_bounds_get(C, gz, &bounds)) {
+ init_position[0] = bounds.xmin;
+ init_position[1] = bounds.ymin;
+ }
}
return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index ff42d434f29..91ad6619889 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -510,11 +510,19 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
const char *global_menu_prefix = NULL;
if (include_all_areas) {
+ bScreen *screen = WM_window_get_active_screen(win);
+
/* First create arrays for ui_type. */
PropertyRNA *prop_ui_type = NULL;
{
+ /* This must be a valid pointer, with only it's type checked. */
+ ScrArea area_dummy = {
+ /* Anything besides #SPACE_EMPTY is fine,
+ * as this value is only included in the enum when set. */
+ .spacetype = SPACE_TOPBAR,
+ };
PointerRNA ptr;
- RNA_pointer_create(NULL, &RNA_Area, NULL, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_Area, &area_dummy, &ptr);
prop_ui_type = RNA_struct_find_property(&ptr, "ui_type");
RNA_property_enum_items(C,
&ptr,
@@ -529,7 +537,6 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
}
- bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (region != NULL) {
@@ -1141,6 +1148,7 @@ void UI_but_func_menu_search(uiBut *but)
ui_searchbox_create_menu,
menu_search_update_fn,
data,
+ false,
menu_search_arg_free_fn,
menu_search_exec_fn,
NULL);
diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c
index 2c83f184ff0..2b765a1a2f5 100644
--- a/source/blender/editors/interface/interface_template_search_operator.c
+++ b/source/blender/editors/interface/interface_template_search_operator.c
@@ -121,6 +121,7 @@ void UI_but_func_operator_search(uiBut *but)
operator_search_update_fn,
NULL,
false,
+ NULL,
operator_search_exec_fn,
NULL);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 2d1663a3ecd..3990ad68c4d 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -309,6 +309,7 @@ static uiBlock *template_common_search_menu(const bContext *C,
ui_searchbox_create_generic,
search_update_fn,
search_arg,
+ false,
NULL,
search_exec_fn,
active_item);
@@ -652,7 +653,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
/* Only remap that specific ID usage to overriding local data-block. */
ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_newptr_and_tag_clear(bmain);
if (GS(override_id->name) == ID_OB) {
Scene *scene = CTX_data_scene(C);
@@ -671,7 +672,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
}
else {
if (BKE_lib_id_make_local(bmain, id, false, 0)) {
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_newptr_and_tag_clear(bmain);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
@@ -1077,7 +1078,7 @@ static void template_ID(const bContext *C,
char numstr[32];
short numstr_len;
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
but = uiDefBut(
block,
@@ -1109,7 +1110,7 @@ static void template_ID(const bContext *C,
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) &&
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_OB, ID_WS)) &&
(hide_buttons == false)) {
uiDefIconButR(block,
UI_BTYPE_ICON_TOGGLE,
@@ -6829,6 +6830,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
uiLayout *ui_abs = uiLayoutAbsolute(layout, false);
uiBlock *block = uiLayoutGetBlock(ui_abs);
+ eUIEmbossType previous_emboss = UI_block_emboss_get(block);
UI_fontstyle_set(&style->widgetlabel);
int width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
@@ -6903,6 +6905,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
width + UI_UNIT_X,
UI_UNIT_Y,
"Show in Info Log");
+
+ UI_block_emboss_set(block, previous_emboss);
}
void uiTemplateInputStatus(uiLayout *layout, struct bContext *C)
@@ -7191,7 +7195,7 @@ void uiTemplateComponentMenu(uiLayout *layout,
/** \name Node Socket Icon Template
* \{ */
-void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
+void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float color[4])
{
uiBlock *block = uiLayoutGetBlock(layout);
UI_block_align_begin(block);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 0c6be7b1196..fe6a8b0d1a6 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1225,12 +1225,6 @@ static bool draw_widgetbase_batch_skip_draw_cache(void)
return true;
}
- /* There are also reports that some AMD and Mesa driver configuration suffer from the
- * same issue, T78803. */
- if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
- return true;
- }
-
return false;
}
@@ -1936,19 +1930,27 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle,
}
#endif /* WITH_INPUT_IME */
-static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str),
+struct UnderlineData {
+ size_t str_offset; /* The string offset of the underlined character. */
+ int width_px; /* The underline width in pixels. */
+ int r_offset_px[2]; /* Write the X,Y offset here. */
+};
+
+static bool widget_draw_text_underline_calc_position(const char *UNUSED(str),
const size_t str_step_ofs,
const rcti *glyph_step_bounds,
const int UNUSED(glyph_advance_x),
const rctf *glyph_bounds,
- const int glyph_bearing[2],
+ const int UNUSED(glyph_bearing[2]),
void *user_data)
{
- /* The index of the character to get, set to the x-position. */
- int *ul_data = user_data;
- if (ul_data[0] == (int)str_step_ofs) {
- ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] +
- (BLI_rctf_size_x(glyph_bounds) / 2.0f);
+ struct UnderlineData *ul_data = user_data;
+ if (ul_data->str_offset == str_step_ofs) {
+ /* Full width of this glyph including both bearings. */
+ const float width = glyph_bounds->xmin + BLI_rctf_size_x(glyph_bounds) + glyph_bounds->xmin;
+ ul_data->r_offset_px[0] = glyph_step_bounds->xmin + ((width - ul_data->width_px) * 0.5f);
+ /* Two line-widths below the lower glyph bounds. */
+ ul_data->r_offset_px[1] = glyph_bounds->ymin - U.pixelsize - U.pixelsize;
/* Early exit. */
return false;
}
@@ -2204,23 +2206,30 @@ static void widget_draw_text(const uiFontStyle *fstyle,
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
- int ul_data[2] = {
- ul_index, /* Character index to test. */
- 0, /* Write the x-offset here. */
+ int ul_width = round_fl_to_int(BLF_width(fstyle->uifont_id, "_", 2));
+ int ul_height = max_ii(fstyle->points * U.dpi_fac * 0.1f, U.pixelsize);
+
+ struct UnderlineData ul_data = {
+ .str_offset = ul_index,
+ .width_px = ul_width,
};
+
BLF_boundbox_foreach_glyph(fstyle->uifont_id,
drawstr_ofs,
ul_index + 1,
- widget_draw_text_underline_calc_center_x,
- ul_data);
- ul_data[1] -= BLF_width(fstyle->uifont_id, "_", 2) / 2.0f;
-
- BLF_position(fstyle->uifont_id,
- rect->xmin + font_xofs + ul_data[1],
- rect->ymin + font_yofs,
- 0.0f);
- BLF_color4ubv(fstyle->uifont_id, wcol->text);
- BLF_draw(fstyle->uifont_id, "_", 2);
+ widget_draw_text_underline_calc_position,
+ &ul_data);
+
+ GPU_blend(GPU_BLEND_ALPHA);
+ const uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(wcol->text);
+ const int pos_x = rect->xmin + font_xofs + ul_data.r_offset_px[0];
+ const int pos_y = rect->ymin + font_yofs + ul_data.r_offset_px[1];
+ immRecti(pos, pos_x, pos_y, pos_x + ul_width, pos_y - ul_height);
+ immUnbindProgram();
+ GPU_blend(GPU_BLEND_NONE);
if (fstyle->kerning == 1) {
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -2422,11 +2431,12 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
but->block->aspect = aspect_orig;
#endif
- rect->xmin += icon_size + icon_padding;
+ rect->xmin += round_fl_to_int(icon_size + icon_padding);
}
if (!no_text_padding) {
- const int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ const int text_padding = round_fl_to_int((UI_TEXT_MARGIN_X * U.widget_unit) /
+ but->block->aspect);
if (but->editstr) {
rect->xmin += text_padding;
}
@@ -3757,12 +3767,35 @@ static void widget_numslider(
float factor, factor_ui;
float factor_discard = 1.0f; /* No discard. */
const float value = (float)ui_but_value_get(but);
-
- if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
- factor = value / but->softmax;
- }
- else {
- factor = (value - but->softmin) / (but->softmax - but->softmin);
+ const float softmin = but->softmin;
+ const float softmax = but->softmax;
+ const float softrange = softmax - softmin;
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
+ factor = value / softmax;
+ }
+ else {
+ factor = (value - softmin) / softrange;
+ }
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float logmin = fmaxf(softmin, 0.5e-8f);
+ const float base = softmax / logmin;
+ factor = logf(value / logmin) / logf(base);
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubicmin = cube_f(softmin);
+ const float cubicmax = cube_f(softmax);
+ const float cubicrange = cubicmax - cubicmin;
+ const float f = (value - softmin) * cubicrange / softrange + cubicmin;
+ factor = (cbrtf(f) - softmin) / softrange;
+ break;
+ }
}
const float width = (float)BLI_rcti_size_x(rect);
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 7453cd17868..40c510af7e5 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -757,7 +757,7 @@ typedef struct v2dViewZoomData {
} v2dViewZoomData;
/**
- * Clamp by convention rather then locking flags,
+ * Clamp by convention rather than locking flags,
* for ndof and +/- keys
*/
static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2])