Sculpt: Sculpt cursor UX improvements
This commit introduces the following changes: - Invert the direction of the brush strength WM control. It was working in the opposite direction to any other control in Blender. Now dragging to the right increases the strength. - Increase the alpha of the cursor - Remove the font shadow of the numbers in the WM control. It was adding too much visual noise when rendered on top of the brush alpha - Add a second circle to preview the strength in the cursor - Increase the resolution of the cursor circles. Now they look smooth even when working with large brush sizes. - Add a line preview to display the brush curve - Don't offset the cursor preview when changing size and strength Reviewed By: billreynish, brecht Differential Revision: https://developer.blender.org/D5889
This commit is contained in:
@@ -90,7 +90,9 @@ float BKE_brush_sample_masktex(const struct Scene *scene,
|
|||||||
unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool use_secondary);
|
unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool use_secondary);
|
||||||
|
|
||||||
/* radial control */
|
/* radial control */
|
||||||
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary);
|
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br,
|
||||||
|
bool secondary,
|
||||||
|
bool display_gradient);
|
||||||
|
|
||||||
/* unified strength size and color */
|
/* unified strength size and color */
|
||||||
|
|
||||||
|
|||||||
@@ -1596,11 +1596,11 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**** Radial Control ****/
|
/**** Radial Control ****/
|
||||||
struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
|
struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
|
||||||
{
|
{
|
||||||
ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
|
ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
|
||||||
unsigned int *texcache;
|
unsigned int *texcache;
|
||||||
int side = 128;
|
int side = 512;
|
||||||
int half = side / 2;
|
int half = side / 2;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@@ -1609,15 +1609,17 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
|
|||||||
im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect");
|
im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect");
|
||||||
im->x = im->y = side;
|
im->x = im->y = side;
|
||||||
|
|
||||||
for (i = 0; i < side; i++) {
|
if (display_gradient || texcache) {
|
||||||
for (j = 0; j < side; j++) {
|
for (i = 0; i < side; i++) {
|
||||||
float magn = sqrtf(pow2f(i - half) + pow2f(j - half));
|
for (j = 0; j < side; j++) {
|
||||||
im->rect_float[i * side + j] = BKE_brush_curve_strength_clamped(br, magn, half);
|
float magn = sqrtf(pow2f(i - half) + pow2f(j - half));
|
||||||
|
im->rect_float[i * side + j] = BKE_brush_curve_strength_clamped(br, magn, half);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modulate curve with texture */
|
|
||||||
if (texcache) {
|
if (texcache) {
|
||||||
|
/* Modulate curve with texture */
|
||||||
for (i = 0; i < side; i++) {
|
for (i = 0; i < side; i++) {
|
||||||
for (j = 0; j < side; j++) {
|
for (j = 0; j < side; j++) {
|
||||||
const int col = texcache[i * side + j];
|
const int col = texcache[i * side + j];
|
||||||
@@ -1626,7 +1628,6 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
|
|||||||
3.0f / 255.0f;
|
3.0f / 255.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(texcache);
|
MEM_freeN(texcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1261,7 +1261,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
|||||||
|
|
||||||
/* set various defaults */
|
/* set various defaults */
|
||||||
const float *outline_col = brush->add_col;
|
const float *outline_col = brush->add_col;
|
||||||
const float outline_alpha = 0.5f;
|
const float outline_alpha = 0.7f;
|
||||||
float translation[2] = {x, y};
|
float translation[2] = {x, y};
|
||||||
float final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
|
float final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
|
||||||
|
|
||||||
@@ -1434,7 +1434,11 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
|||||||
GPU_matrix_mul(cursor_trans);
|
GPU_matrix_mul(cursor_trans);
|
||||||
GPU_matrix_mul(cursor_rot);
|
GPU_matrix_mul(cursor_rot);
|
||||||
immUniformColor3fvAlpha(outline_col, outline_alpha);
|
immUniformColor3fvAlpha(outline_col, outline_alpha);
|
||||||
imm_draw_circle_wire_3d(pos, 0, 0, rds, 40);
|
GPU_line_width(2.0f);
|
||||||
|
imm_draw_circle_wire_3d(pos, 0, 0, rds, 80);
|
||||||
|
GPU_line_width(1.0f);
|
||||||
|
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
|
||||||
|
imm_draw_circle_wire_3d(pos, 0, 0, rds * clamp_f(brush->alpha, 0.0f, 1.0f), 80);
|
||||||
GPU_matrix_pop();
|
GPU_matrix_pop();
|
||||||
|
|
||||||
/* Update and draw dynamic mesh preview lines */
|
/* Update and draw dynamic mesh preview lines */
|
||||||
@@ -1467,7 +1471,15 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
|||||||
/* Draw default cursor when the mouse is not over the mesh or there are no supported
|
/* Draw default cursor when the mouse is not over the mesh or there are no supported
|
||||||
* overlays active */
|
* overlays active */
|
||||||
GPU_line_width(1.0f);
|
GPU_line_width(1.0f);
|
||||||
imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40);
|
/* Reduce alpha to increase the contrast when the cursor is over the mesh */
|
||||||
|
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.8);
|
||||||
|
imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 80);
|
||||||
|
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.35f);
|
||||||
|
imm_draw_circle_wire_3d(pos,
|
||||||
|
translation[0],
|
||||||
|
translation[1],
|
||||||
|
final_radius * clamp_f(brush->alpha, 0.0f, 1.0f),
|
||||||
|
80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "CLG_log.h"
|
#include "CLG_log.h"
|
||||||
|
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_screen_types.h"
|
#include "DNA_screen_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
|
#include "BKE_colortools.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_icons.h"
|
#include "BKE_icons.h"
|
||||||
@@ -1862,6 +1864,7 @@ typedef struct {
|
|||||||
StructRNA *image_id_srna;
|
StructRNA *image_id_srna;
|
||||||
float initial_value, current_value, min_value, max_value;
|
float initial_value, current_value, min_value, max_value;
|
||||||
int initial_mouse[2];
|
int initial_mouse[2];
|
||||||
|
int initial_co[2];
|
||||||
int slow_mouse[2];
|
int slow_mouse[2];
|
||||||
bool slow_mode;
|
bool slow_mode;
|
||||||
Dial *dial;
|
Dial *dial;
|
||||||
@@ -1924,6 +1927,9 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e
|
|||||||
rc->initial_mouse[0] = event->x;
|
rc->initial_mouse[0] = event->x;
|
||||||
rc->initial_mouse[1] = event->y;
|
rc->initial_mouse[1] = event->y;
|
||||||
|
|
||||||
|
rc->initial_co[0] = event->x;
|
||||||
|
rc->initial_co[1] = event->y;
|
||||||
|
|
||||||
switch (rc->subtype) {
|
switch (rc->subtype) {
|
||||||
case PROP_NONE:
|
case PROP_NONE:
|
||||||
case PROP_DISTANCE:
|
case PROP_DISTANCE:
|
||||||
@@ -1935,7 +1941,7 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e
|
|||||||
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
||||||
break;
|
break;
|
||||||
case PROP_FACTOR:
|
case PROP_FACTOR:
|
||||||
d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
|
d[0] = rc->initial_value * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
|
||||||
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
||||||
break;
|
break;
|
||||||
case PROP_ANGLE:
|
case PROP_ANGLE:
|
||||||
@@ -1962,8 +1968,10 @@ static void radial_control_set_tex(RadialControl *rc)
|
|||||||
|
|
||||||
switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
|
switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
|
||||||
case ID_BR:
|
case ID_BR:
|
||||||
if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data,
|
if ((ibuf = BKE_brush_gen_radial_control_imbuf(
|
||||||
rc->use_secondary_tex))) {
|
rc->image_id_ptr.data,
|
||||||
|
rc->use_secondary_tex,
|
||||||
|
!ELEM(rc->subtype, PROP_NONE, PROP_PIXEL, PROP_DISTANCE)))) {
|
||||||
glGenTextures(1, &rc->gltex);
|
glGenTextures(1, &rc->gltex);
|
||||||
glBindTexture(GL_TEXTURE_2D, rc->gltex);
|
glBindTexture(GL_TEXTURE_2D, rc->gltex);
|
||||||
glTexImage2D(
|
glTexImage2D(
|
||||||
@@ -2061,6 +2069,22 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
|
|||||||
immUnbindProgram();
|
immUnbindProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void radial_control_paint_curve(uint pos, Brush *br, float radius, int line_segments)
|
||||||
|
{
|
||||||
|
GPU_line_width(2.0f);
|
||||||
|
immUniformColor4f(0.8f, 0.8f, 0.8f, 0.85f);
|
||||||
|
float step = (radius * 2.0f) / (float)line_segments;
|
||||||
|
BKE_curvemapping_initialize(br->curve);
|
||||||
|
immBegin(GPU_PRIM_LINES, line_segments * 2);
|
||||||
|
for (int i = 0; i < line_segments; i++) {
|
||||||
|
float h1 = BKE_brush_curve_strength_clamped(br, fabsf((i * step) - radius), radius);
|
||||||
|
immVertex2f(pos, -radius + (i * step), h1 * radius);
|
||||||
|
float h2 = BKE_brush_curve_strength_clamped(br, fabsf(((i + 1) * step) - radius), radius);
|
||||||
|
immVertex2f(pos, -radius + ((i + 1) * step), h2 * radius);
|
||||||
|
}
|
||||||
|
immEnd();
|
||||||
|
}
|
||||||
|
|
||||||
static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void *customdata)
|
static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void *customdata)
|
||||||
{
|
{
|
||||||
RadialControl *rc = customdata;
|
RadialControl *rc = customdata;
|
||||||
@@ -2094,7 +2118,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
|
|||||||
alpha = 0.75;
|
alpha = 0.75;
|
||||||
break;
|
break;
|
||||||
case PROP_FACTOR:
|
case PROP_FACTOR:
|
||||||
r1 = (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
|
r1 = rc->current_value * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
|
||||||
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
||||||
r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||||
rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
|
||||||
@@ -2115,9 +2139,17 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep cursor in the original place */
|
if (rc->subtype == PROP_ANGLE) {
|
||||||
x = rc->initial_mouse[0];
|
/* Use the initial mouse position to draw the rotation preview. This avoids starting the
|
||||||
y = rc->initial_mouse[1];
|
* rotation in a random direction */
|
||||||
|
x = rc->initial_mouse[0];
|
||||||
|
y = rc->initial_mouse[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Keep cursor in the original place */
|
||||||
|
x = rc->initial_co[0];
|
||||||
|
y = rc->initial_co[1];
|
||||||
|
}
|
||||||
GPU_matrix_translate_2f((float)x, (float)y);
|
GPU_matrix_translate_2f((float)x, (float)y);
|
||||||
|
|
||||||
GPU_blend(true);
|
GPU_blend(true);
|
||||||
@@ -2141,7 +2173,6 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
|
|||||||
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||||
|
|
||||||
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
||||||
immUniformColor3fvAlpha(col, 0.5f);
|
|
||||||
|
|
||||||
if (rc->subtype == PROP_ANGLE) {
|
if (rc->subtype == PROP_ANGLE) {
|
||||||
GPU_matrix_push();
|
GPU_matrix_push();
|
||||||
@@ -2164,25 +2195,40 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* draw circles on top */
|
/* draw circles on top */
|
||||||
imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 40);
|
GPU_line_width(2.0f);
|
||||||
imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 40);
|
immUniformColor3fvAlpha(col, 0.8f);
|
||||||
|
imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 80);
|
||||||
|
|
||||||
|
GPU_line_width(1.0f);
|
||||||
|
immUniformColor3fvAlpha(col, 0.5f);
|
||||||
|
imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 80);
|
||||||
if (rmin > 0.0f) {
|
if (rmin > 0.0f) {
|
||||||
imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 40);
|
/* Inner fill circle to increase the contrast of the value */
|
||||||
|
float black[3] = {0.0f};
|
||||||
|
immUniformColor3fvAlpha(black, 0.2f);
|
||||||
|
imm_draw_circle_fill_2d(pos, 0.0, 0.0f, rmin, 80);
|
||||||
|
|
||||||
|
immUniformColor3fvAlpha(col, 0.5f);
|
||||||
|
imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* draw curve falloff preview */
|
||||||
|
if (RNA_type_to_ID_code(rc->image_id_ptr.type) == ID_BR && rc->subtype == PROP_FACTOR) {
|
||||||
|
Brush *br = rc->image_id_ptr.data;
|
||||||
|
if (br) {
|
||||||
|
radial_control_paint_curve(pos, br, r2, 120);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
immUnbindProgram();
|
immUnbindProgram();
|
||||||
|
|
||||||
BLF_size(fontid, 1.5 * fstyle_points * U.pixelsize, U.dpi);
|
BLF_size(fontid, 1.75f * fstyle_points * U.pixelsize, U.dpi);
|
||||||
BLF_enable(fontid, BLF_SHADOW);
|
|
||||||
BLF_shadow(fontid, 3, (const float[4]){0.0f, 0.0f, 0.0f, 0.5f});
|
|
||||||
BLF_shadow_offset(fontid, 1, -1);
|
|
||||||
|
|
||||||
/* draw value */
|
/* draw value */
|
||||||
BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
|
BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
|
||||||
BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
|
BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
|
||||||
BLF_draw(fontid, str, strdrawlen);
|
BLF_draw(fontid, str, strdrawlen);
|
||||||
|
|
||||||
BLF_disable(fontid, BLF_SHADOW);
|
|
||||||
|
|
||||||
GPU_blend(false);
|
GPU_blend(false);
|
||||||
GPU_line_smooth(false);
|
GPU_line_smooth(false);
|
||||||
}
|
}
|
||||||
@@ -2633,6 +2679,8 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||||||
if (snap) {
|
if (snap) {
|
||||||
new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
|
new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
|
||||||
}
|
}
|
||||||
|
/* Invert new value to increase the factor moving the mouse to the right */
|
||||||
|
new_value = 1 - new_value;
|
||||||
break;
|
break;
|
||||||
case PROP_ANGLE:
|
case PROP_ANGLE:
|
||||||
new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision;
|
new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision;
|
||||||
|
|||||||
Reference in New Issue
Block a user