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:
authorHans Goudey <h.goudey@me.com>2019-11-21 00:12:32 +0300
committerHans Goudey <h.goudey@me.com>2019-11-21 00:25:28 +0300
commitba1e9ae4733ae956331c7e8899f6939997205298 (patch)
tree007362ed2c9ee4564b67404f552906d6e66848db /source/blender/editors/interface/interface_draw.c
parent8c6ce742391b2b8798143a4a2c2224ebbeb7f1ec (diff)
Bevel: Custom Profile and CurveProfile Widget
Custom profiles in bevel allows the profile curve to be controlled by manually placed control points. Orientation is regularized along groups of edges, and the 'pipe case' is updated. This commit includes many updates to comments and changed variable names as well. A 'cutoff' vertex mesh method is added to bevel in addition to the existing grid fill option for replacing vertices. The UI of the bevel modifier and tool are updated and unified. Also, a 'CurveProfile' widget is added to BKE for defining the profile in the interface, which may be useful in other situations. Many thanks to Howard, my mentor for this GSoC project. Reviewers: howardt, campbellbarton Differential Revision: https://developer.blender.org/D5516
Diffstat (limited to 'source/blender/editors/interface/interface_draw.c')
-rw-r--r--source/blender/editors/interface/interface_draw.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 72c31c7b39e..499842a570b 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -27,16 +27,21 @@
#include "DNA_color_types.h"
#include "DNA_screen_types.h"
#include "DNA_movieclip_types.h"
+#include "DNA_curveprofile_types.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLI_polyfill_2d.h"
+
+#include "MEM_guardedalloc.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_node.h"
#include "BKE_tracking.h"
+#include "BKE_curveprofile.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -1814,6 +1819,8 @@ static void ui_draw_but_curve_grid(
immVertex2f(pos, rect->xmax, fy);
fy += dy;
}
+ /* Note: Assertion fails with here when the view is moved farther below the center.
+ * Missing two points from the number given with immBegin. */
immEnd();
}
@@ -2113,6 +2120,231 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons
immUnbindProgram();
}
+/** Used to draw a curve profile widget. Somewhat similar to ui_draw_but_CURVE */
+void ui_draw_but_CURVEPROFILE(ARegion *ar,
+ uiBut *but,
+ const uiWidgetColors *wcol,
+ const rcti *rect)
+{
+ uint i;
+ float fx, fy;
+ CurveProfile *profile;
+ if (but->editprofile) {
+ profile = but->editprofile;
+ }
+ else {
+ profile = (CurveProfile *)but->poin;
+ }
+
+ /* Calculate offset and zoom */
+ float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&profile->view_rect);
+ float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&profile->view_rect);
+ float offsx = profile->view_rect.xmin - (1.0f / zoomx);
+ float offsy = profile->view_rect.ymin - (1.0f / zoomy);
+
+ /* Exit early if too narrow */
+ if (zoomx == 0.0f) {
+ return;
+ }
+
+ /* Test needed because path can draw outside of boundary */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ rcti scissor_new = {
+ .xmin = rect->xmin,
+ .ymin = rect->ymin,
+ .xmax = rect->xmax,
+ .ymax = rect->ymax,
+ };
+ rcti scissor_region = {0, ar->winx, 0, ar->winy};
+ BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
+ GPU_scissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ GPU_line_width(1.0f);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* Backdrop */
+ float color_backdrop[4] = {0, 0, 0, 1};
+ if (profile->flag & PROF_USE_CLIP) {
+ gl_shaded_color_get_fl((uchar *)wcol->inner, -20, color_backdrop);
+ immUniformColor3fv(color_backdrop);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((uchar *)wcol->inner);
+ immRectf(pos,
+ rect->xmin + zoomx * (profile->clip_rect.xmin - offsx),
+ rect->ymin + zoomy * (profile->clip_rect.ymin - offsy),
+ rect->xmin + zoomx * (profile->clip_rect.xmax - offsx),
+ rect->ymin + zoomy * (profile->clip_rect.ymax - offsy));
+ }
+ else {
+ rgb_uchar_to_float(color_backdrop, (uchar *)wcol->inner);
+ immUniformColor3fv(color_backdrop);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+
+ /* 0.25 step grid */
+ gl_shaded_color((uchar *)wcol->inner, -16);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
+ /* 1.0 step grid */
+ gl_shaded_color((uchar *)wcol->inner, -24);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
+
+ /* Draw the path's fill */
+ if (profile->table == NULL) {
+ BKE_curveprofile_update(profile, false);
+ }
+ CurveProfilePoint *pts = profile->table;
+ /* Also add the last points on the right and bottom edges to close off the fill polygon */
+ bool add_left_tri = profile->view_rect.xmin < 0.0f;
+ bool add_bottom_tri = profile->view_rect.ymin < 0.0f;
+ uint tot_points = (uint)PROF_N_TABLE(profile->path_len) + 1 + add_left_tri + add_bottom_tri;
+ uint tot_triangles = tot_points - 2;
+
+ /* Create array of the positions of the table's points */
+ float(*table_coords)[2] = MEM_mallocN(sizeof(*table_coords) * tot_points, "table x coords");
+ for (i = 0; i < (uint)PROF_N_TABLE(profile->path_len);
+ i++) { /* Only add the points from the table here */
+ table_coords[i][0] = pts[i].x;
+ table_coords[i][1] = pts[i].y;
+ }
+ if (add_left_tri && add_bottom_tri) {
+ /* Add left side, bottom left corner, and bottom side points */
+ table_coords[tot_points - 3][0] = profile->view_rect.xmin;
+ table_coords[tot_points - 3][1] = 1.0f;
+ table_coords[tot_points - 2][0] = profile->view_rect.xmin;
+ table_coords[tot_points - 2][1] = profile->view_rect.ymin;
+ table_coords[tot_points - 1][0] = 1.0f;
+ table_coords[tot_points - 1][1] = profile->view_rect.ymin;
+ }
+ else if (add_left_tri) {
+ /* Add the left side and bottom left corner points */
+ table_coords[tot_points - 2][0] = profile->view_rect.xmin;
+ table_coords[tot_points - 2][1] = 1.0f;
+ table_coords[tot_points - 1][0] = profile->view_rect.xmin;
+ table_coords[tot_points - 1][1] = 0.0f;
+ }
+ else if (add_bottom_tri) {
+ /* Add the bottom side and bottom left corner points */
+ table_coords[tot_points - 2][0] = 0.0f;
+ table_coords[tot_points - 2][1] = profile->view_rect.ymin;
+ table_coords[tot_points - 1][0] = 1.0f;
+ table_coords[tot_points - 1][1] = profile->view_rect.ymin;
+ }
+ else {
+ /* Just add the bottom corner point. Side points would be redundant anyway */
+ table_coords[tot_points - 1][0] = 0.0f;
+ table_coords[tot_points - 1][1] = 0.0f;
+ }
+
+ /* Calculate the table point indices of the triangles for the profile's fill */
+ uint(*tri_indices)[3] = MEM_mallocN(sizeof(*tri_indices) * tot_triangles, "return tri indices");
+ BLI_polyfill_calc(table_coords, tot_points, -1, tri_indices);
+
+ /* Draw the triangles for the profile fill */
+ immUniformColor3ubvAlpha((const uchar *)wcol->item, 128);
+ GPU_blend(true);
+ GPU_polygon_smooth(false);
+ immBegin(GPU_PRIM_TRIS, 3 * tot_triangles);
+ for (i = 0; i < tot_triangles; i++) {
+ for (uint j = 0; j < 3; j++) {
+ uint *tri = tri_indices[i];
+ fx = rect->xmin + zoomx * (table_coords[tri[j]][0] - offsx);
+ fy = rect->ymin + zoomy * (table_coords[tri[j]][1] - offsy);
+ immVertex2f(pos, fx, fy);
+ }
+ }
+ immEnd();
+ MEM_freeN(tri_indices);
+
+ /* Draw the profile's path so the edge stands out a bit */
+ tot_points -= (add_left_tri + add_left_tri);
+ GPU_line_width(1.0f);
+ immUniformColor3ubvAlpha((const uchar *)wcol->item, 255);
+ GPU_line_smooth(true);
+ immBegin(GPU_PRIM_LINE_STRIP, tot_points - 1);
+ for (i = 0; i < tot_points - 1; i++) {
+ fx = rect->xmin + zoomx * (table_coords[i][0] - offsx);
+ fy = rect->ymin + zoomy * (table_coords[i][1] - offsy);
+ immVertex2f(pos, fx, fy);
+ }
+ immEnd();
+ immUnbindProgram();
+ MEM_freeN(table_coords);
+
+ /* New GPU instructions for control points and sampled points. */
+ format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ /* Calculate vertex colors based on text theme. */
+ float color_vert[4], color_vert_select[4], color_sample[4];
+ UI_GetThemeColor4fv(TH_TEXT_HI, color_vert);
+ UI_GetThemeColor4fv(TH_TEXT, color_vert_select);
+ color_sample[0] = (float)wcol->item[0] / 255.0f;
+ color_sample[1] = (float)wcol->item[1] / 255.0f;
+ color_sample[2] = (float)wcol->item[2] / 255.0f;
+ color_sample[3] = (float)wcol->item[3] / 255.0f;
+ if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) {
+ interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f);
+ }
+ if (len_squared_v3(color_vert) > len_squared_v3(color_vert_select)) {
+ /* Ensure brightest text color is used for selection. */
+ swap_v3_v3(color_vert, color_vert_select);
+ }
+
+ /* Draw the control points. */
+ pts = profile->path;
+ tot_points = (uint)profile->path_len;
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ GPU_point_size(max_ff(3.0f, min_ff(UI_DPI_FAC / but->block->aspect * 5.0f, 5.0f)));
+ immBegin(GPU_PRIM_POINTS, tot_points);
+ for (i = 0; i < tot_points; i++) {
+ fx = rect->xmin + zoomx * (pts[i].x - offsx);
+ fy = rect->ymin + zoomy * (pts[i].y - offsy);
+ immAttr4fv(col, (pts[i].flag & PROF_SELECT) ? color_vert_select : color_vert);
+ immVertex2f(pos, fx, fy);
+ }
+ immEnd();
+
+ /* Draw the sampled points in addition to the control points if they have been created */
+ pts = profile->segments;
+ tot_points = (uint)profile->segments_len;
+ if (tot_points > 0 && pts) {
+ GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 3.0f, 3.0f)));
+ immBegin(GPU_PRIM_POINTS, tot_points);
+ for (i = 0; i < tot_points; i++) {
+ fx = rect->xmin + zoomx * (pts[i].x - offsx);
+ fy = rect->ymin + zoomy * (pts[i].y - offsy);
+ immAttr4fv(col, color_sample);
+ immVertex2f(pos, fx, fy);
+ }
+ immEnd();
+ }
+
+ immUnbindProgram();
+
+ /* restore scissortest */
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+
+ /* Outline */
+ format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv((const uchar *)wcol->outline);
+ imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ immUnbindProgram();
+}
+
void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),