UI: uiBut Indeterminate State #108210

Merged
Julian Eisel merged 15 commits from Harley/blender:Indeterminate into main 2023-07-17 19:37:24 +02:00
4 changed files with 30 additions and 33 deletions
Showing only changes of commit c5d5f569e9 - Show all commits

View File

@ -2304,7 +2304,7 @@ int ui_but_is_pushed(uiBut *but)
static void ui_but_update_select_flag(uiBut *but, double *value)
{
switch (ui_but_is_pushed_ex(but, value) && (!(but->drawflag & UI_BUT_INDETERMINATE)))
switch (ui_but_is_pushed_ex(but, value))
{
case true:
but->flag |= UI_SELECT;
@ -3786,10 +3786,6 @@ static void ui_but_build_drawstr_int(uiBut *but, int value)
*/
static void ui_but_update_ex(uiBut *but, const bool validate)
{
if (but->type != UI_BTYPE_LABEL) {
but->drawflag |= UI_BUT_INDETERMINATE;
}
/* if something changed in the button */
double value = UI_BUT_VALUE_UNSET;
@ -3798,6 +3794,10 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
ui_but_update_select_flag(but, &value);
if ((but->drawflag & UI_BUT_INDETERMINATE) && (but->flag & UI_SELECT)) {
but->flag &= ~UI_SELECT;
Harley marked this conversation as resolved Outdated

I still can't see an explanation on why this is done, only what it does. Testing the patch, when I simply enable UI_BUT_INDETERMINATE for all buttons, I get a whole bunch of interaction issues/glitches. That is because UI_SELECT is supposed to impact the behavior, not just the drawing.

I guess this should only affect drawing (it's controlled by a draw flag after all), so this should probably be done in ui_draw_but(). At the end of that we already do similar things to safely manipulate flags for drawing.

I still can't see an explanation on _why_ this is done, only what it does. Testing the patch, when I simply enable `UI_BUT_INDETERMINATE` for all buttons, I get a whole bunch of interaction issues/glitches. That is because `UI_SELECT` is supposed to impact the behavior, not just the drawing. I guess this should only affect drawing (it's controlled by a draw flag after all), so this should probably be done in `ui_draw_but()`. At the end of that we already do similar things to safely manipulate flags for drawing.
}
Harley marked this conversation as resolved Outdated

I'd rather avoid flags that silently change other flags. Why exactly is this needed?

I'd rather avoid flags that silently change other flags. Why exactly is this needed?
/* only update soft range while not editing */
if (!ui_but_is_editing(but)) {
if ((but->rnaprop != nullptr) || (but->poin && (but->pointype & UI_BUT_POIN_TYPES))) {

View File

@ -1111,6 +1111,7 @@ enum {
ROUNDBOX_TRIA_MENU,
ROUNDBOX_TRIA_CHECK,
ROUNDBOX_TRIA_HOLD_ACTION_ARROW,
ROUNDBOX_TRIA_DASH,
ROUNDBOX_TRIA_MAX, /* don't use */
};

View File

@ -1031,6 +1031,16 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc
tria->index = g_shape_preset_checkmark_face;
}
static void shape_preset_trias_from_rect_dash(uiWidgetTrias *tria, const rcti *rect)
{
tria->type = ROUNDBOX_TRIA_DASH;
/* Center position and size. */
tria->center[0] = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
tria->center[1] = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
tria->size = 0.5f * BLI_rcti_size_y(rect);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -4157,44 +4167,22 @@ static void widget_optionbut(uiWidgetColors *wcol,
if (state->but_drawflag & UI_BUT_INDETERMINATE) {
/* The same muted background color regardless of state. */
wcol->inner[0] = wcol->inner_sel[0];
wcol->inner[1] = wcol->inner_sel[1];
wcol->inner[2] = wcol->inner_sel[2];
wcol->inner[3] = 60;
color_blend_v4_v4v4(wcol->inner, wcol->inner, wcol->inner_sel, 0.75f);
}
const float rad = widget_radius_from_rcti(&recttemp, wcol);
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
/* decoration */
if (state->but_flag & UI_SELECT && !(state->but_drawflag & UI_BUT_INDETERMINATE)) {
if (state->but_drawflag & UI_BUT_INDETERMINATE) {
shape_preset_trias_from_rect_dash(&wtb.tria1, &recttemp);
}
else if (state->but_flag & UI_SELECT) {
Harley marked this conversation as resolved Outdated

We should avoid flushing the widget cache, this can introduce slowdowns (there were significant slowdowns in widget drawing in early 2.8, before adding the cache). It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see shape_preset_init_number_arrows().

We should avoid flushing the widget cache, this can introduce slowdowns (there were significant slowdowns in widget drawing in early 2.8, before adding the cache). It should be trivial to draw a line in the widget shader, without immediate mode drawing. E.g. see `shape_preset_init_number_arrows()`.
shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
}
widgetbase_draw(&wtb, wcol);
if (state->but_drawflag & UI_BUT_INDETERMINATE) {
/* Flush the widget cache so we can draw on top. */
GPU_blend(GPU_BLEND_ALPHA);
UI_widgetbase_draw_cache_flush();
/* Draw a horizontal line instead of checkmark. */
const uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3ubvAlpha(wcol->text, 192);
const float extent = (recttemp.ymax - recttemp.ymin);
const float w = extent * 0.6f;
const float h = MAX2(w / 6.0f, U.pixelsize);
const float x = recttemp.xmin + (extent * 0.2f);
const float y = recttemp.ymin + (extent * 0.5f) - (h * 0.5f);
immRectf(pos, x, y, x + w, y + h);
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
}
/* Text space - factor is really just eyeballed. */
const float offset = delta * 0.9;
if (text_before_widget) {

View File

@ -137,7 +137,7 @@ vec2 do_tria()
outRectSize = vec2(0.74, 0.14);
outRoundCorners = vec4(0.01);
}
else {
else if (triaType == 5.0) {
/* ROUNDBOX_TRIA_HOLD_ACTION_ARROW */
/* We use a single triangle to cut the round rect in half. The edge will not be Antialiased. */
pos = tria2 ? vec2(0.0) : arrow_pos[min(vidx, 2)]; /* Only keep 1 triangle. */
@ -149,6 +149,14 @@ vec2 do_tria()
outRectSize = vec2(0.75);
outRoundCorners = vec4(0.01);
}
else if (triaType == 6.0) {
/* ROUNDBOX_TRIA_DASH */
pos = point_pos[vidx];
uvInterp = point_uvs[vidx];
uvInterp -= vec2(0.2, 0.45); /* Translate */
outRectSize = vec2(0.6, 0.1);
outRoundCorners = vec4(0.01);
}
uvInterp *= abs(size);
outRectSize *= abs(size);