diff options
Diffstat (limited to 'source/blender/editors/space_node')
-rw-r--r-- | source/blender/editors/space_node/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 497 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 490 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 15 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 11 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_manipulators.c | 614 | ||||
-rw-r--r-- | source/blender/editors/space_node/space_node.c | 58 |
7 files changed, 1139 insertions, 548 deletions
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index cde818333e4..77b1351435b 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../imbuf ../../gpu ../../makesdna @@ -47,6 +48,7 @@ set(SRC node_draw.c node_edit.c node_group.c + node_manipulators.c node_ops.c node_relationships.c node_select.c diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 7ef34669ee2..67584fbe1f1 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -50,9 +50,12 @@ #include "BLF_api.h" #include "BLT_translation.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -62,6 +65,7 @@ #include "WM_types.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" @@ -80,49 +84,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin uiItemL(layout, text, 0); } - -/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */ - -#if 0 /* UNUSED */ -static void node_draw_socket_new(bNodeSocket *sock, float size) -{ - float x = sock->locx, y = sock->locy; - - /* 16 values of sin function */ - static float si[16] = { - 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f, - 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f, - -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f, - -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f - }; - /* 16 values of cos function */ - static float co[16] = { - 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f, - -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f, - -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f, - 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f, - }; - int a; - - glColor3ub(180, 180, 180); - - glBegin(GL_POLYGON); - for (a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); - - glColor4ub(0, 0, 0, 150); - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); - for (a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); -} -#endif - /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -392,6 +353,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp const int font_size = data->label_size / aspect; const float margin = (float)(NODE_DY / 4); int label_height; + unsigned char color[3]; nodeLabel(ntree, node, label, sizeof(label)); @@ -400,7 +362,8 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */ /* title color */ - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color); + BLF_color3ubv(fontid, color); width = BLF_width(fontid, label, sizeof(label)); ascender = BLF_ascender(fontid); @@ -465,7 +428,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, { rctf *rct = &node->totr; int color_id = node_get_colorid(node); - unsigned char color[4]; + float color[4]; float alpha; /* skip if out of view */ @@ -475,40 +438,32 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, return; } - UI_GetThemeColor4ubv(TH_NODE_FRAME, color); - alpha = (float)(color[3]) / 255.0f; + UI_GetThemeColor4fv(TH_NODE_FRAME, color); + alpha = color[3]; /* shadow */ node_draw_shadow(snode, node, BASIS_RAD, alpha); /* body */ - if (node->flag & NODE_CUSTOM_COLOR) - glColor4f(node->color[0], node->color[1], node->color[2], alpha); + if (node->flag & NODE_CUSTOM_COLOR) { + rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha); + } else - UI_ThemeColor4(TH_NODE_FRAME); - glEnable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE_FRAME, color); + UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); + UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color); else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, - rct->xmin, rct->ymin, - rct->xmax, rct->ymax, BASIS_RAD); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color); + + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); } - + /* label */ node_draw_frame_label(ntree, node, snode->aspect); @@ -580,15 +535,9 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUS static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { - bNodeSocket *sock; char showname[128]; /* 128 used below */ rctf *rct = &node->totr; -#if 0 /* UNUSED */ - float size = NODE_REROUTE_SIZE; -#endif - float socket_size = NODE_SOCKSIZE; - /* skip if out of view */ if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax || node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) @@ -602,23 +551,26 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( * selection state is indicated by socket outline below! */ #if 0 + float size = NODE_REROUTE_SIZE; + /* body */ + float debug_color[4]; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_ThemeColor4(TH_NODE); - glEnable(GL_BLEND); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); - glDisable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE, debug_color); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color); /* outline active and selected emphasis */ if (node->flag & SELECT) { glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); /* using different shades of TH_TEXT_HI for the empasis, like triangle */ - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); + if (node->flag & NODE_ACTIVE) { + UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color); + } + else { + UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color); + } + UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); @@ -637,9 +589,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( /* only draw input socket. as they all are placed on the same position. * highlight also if node itself is selected, since we don't display the node body separately! */ - for (sock = node->inputs.first; sock; sock = sock->next) { - node_socket_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); - } + node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT); UI_block_end(C, node->block); UI_block_draw(C, node->block); @@ -798,7 +748,7 @@ static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_layers", "", ICON_NONE); uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE); } else { @@ -1016,7 +966,7 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } } } @@ -1035,7 +985,7 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else uiItemR(layout, ptr, "uv_map", 0, "", 0); @@ -1057,7 +1007,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else uiItemR(row, ptr, "uv_map", 0, "", 0); @@ -2208,14 +2158,21 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo const float cy = y + snode->zoom * backdropHeight * node->custom4; const float cross_size = 12 * U.pixelsize; - glColor3f(1.0, 1.0, 1.0); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - glBegin(GL_LINES); - glVertex2f(cx - cross_size, cy - cross_size); - glVertex2f(cx + cross_size, cy + cross_size); - glVertex2f(cx + cross_size, cy - cross_size); - glVertex2f(cx - cross_size, cy + cross_size); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, cx - cross_size, cy - cross_size); + immVertex2f(pos, cx + cross_size, cy + cross_size); + immVertex2f(pos, cx + cross_size, cy - cross_size); + immVertex2f(pos, cx - cross_size, cy + cross_size); + immEnd(); + + immUnbindProgram(); } } @@ -2234,9 +2191,6 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN float cx, cy, x1, x2, x3, x4; float y1, y2, y3, y4; - - glColor3f(1.0, 1.0, 1.0); - cx = x + snode->zoom * backdropWidth * boxmask->x; cy = y + snode->zoom * backdropHeight * boxmask->y; @@ -2249,12 +2203,21 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; - glBegin(GL_LINE_LOOP); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glVertex2f(x3, y3); - glVertex2f(x4, y4); - glEnd(); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x3, y3); + immVertex2f(pos, x4, y4); + immEnd(); + + immUnbindProgram(); } static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) @@ -2272,9 +2235,6 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop float cx, cy, x1, x2, x3, x4; float y1, y2, y3, y4; - - glColor3f(1.0, 1.0, 1.0); - cx = x + snode->zoom * backdropWidth * ellipsemask->x; cy = y + snode->zoom * backdropHeight * ellipsemask->y; @@ -2287,13 +2247,21 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom; - glBegin(GL_LINE_LOOP); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3f(1.0f, 1.0f, 1.0f); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glVertex2f(x3, y3); - glVertex2f(x4, y4); - glEnd(); + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x3, y3); + immVertex2f(pos, x4, y4); + immEnd(); + + immUnbindProgram(); } static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -3199,6 +3167,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype) void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key) { bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE); + float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; Image *ima; void *lock; ImBuf *ibuf; @@ -3213,12 +3182,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { float x, y; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - + + gpuPushProjectionMatrix(); + gpuPushMatrix(); + /* somehow the offset has to be calculated inverse */ glaDefine2DArea(&ar->winrct); @@ -3231,60 +3198,37 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b unsigned char *display_buffer = NULL; void *cache_handle = NULL; - if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) { - int ofs; - - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - -#ifdef __BIG_ENDIAN__ - if (snode->flag & SNODE_SHOW_R) ofs = 0; - else if (snode->flag & SNODE_SHOW_G) ofs = 1; - else ofs = 2; -#else - if (snode->flag & SNODE_SHOW_R) ofs = 1; - else if (snode->flag & SNODE_SHOW_G) ofs = 2; - else ofs = 3; -#endif + if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) { - glPixelZoom(snode->zoom, snode->zoom); - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ - - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, - display_buffer - (4 - ofs)); - - glPixelZoom(1.0f, 1.0f); - } - else if (snode->flag & SNODE_SHOW_ALPHA) { display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - glPixelZoom(snode->zoom, snode->zoom); - /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ -#ifdef __BIG_ENDIAN__ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); -#endif - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer); - -#ifdef __BIG_ENDIAN__ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); -#endif - glPixelZoom(1.0f, 1.0f); + + if (snode->flag & SNODE_SHOW_R) + shuffle[0] = 1.0f; + else if (snode->flag & SNODE_SHOW_G) + shuffle[1] = 1.0f; + else if (snode->flag & SNODE_SHOW_B) + shuffle[2] = 1.0f; + else + shuffle[3] = 1.0f; + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); + GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); + + immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, + display_buffer, snode->zoom, snode->zoom, NULL); + + GPU_shader_unbind(); } else if (snode->flag & SNODE_USE_ALPHA) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPixelZoom(snode->zoom, snode->zoom); - - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); - - glPixelZoom(1.0f, 1.0f); + + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom); + glDisable(GL_BLEND); } else { - glPixelZoom(snode->zoom, snode->zoom); - - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); - - glPixelZoom(1.0f, 1.0f); + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom); } if (cache_handle) @@ -3309,20 +3253,24 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b viewer_border->ymin < viewer_border->ymax) { rcti pixel_border; - UI_ThemeColor(TH_ACTIVE); BLI_rcti_init(&pixel_border, x + snode->zoom * viewer_border->xmin * ibuf->x, x + snode->zoom * viewer_border->xmax * ibuf->x, y + snode->zoom * viewer_border->ymin * ibuf->y, y + snode->zoom * viewer_border->ymax * ibuf->y); - glaDrawBorderCorners(&pixel_border, 1.0f, 1.0f); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE); + + immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f); + + immUnbindProgram(); } } - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); } BKE_image_release_ibuf(ima, ibuf, lock); @@ -3434,6 +3382,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, float linew; float arrow[2], arrow1[2], arrow2[2]; glGetFloatv(GL_LINE_WIDTH, &linew); + unsigned int pos; /* we can reuse the dist variable here to increment the GL curve eval amount*/ dist = 1.0f / (float)LINK_RESOL; @@ -3457,141 +3406,89 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, arrow[0] = coord_array[LINK_ARROW][0]; arrow[1] = coord_array[LINK_ARROW][1]; } + + if (do_triple || drawarrow || (!do_shaded)) { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); + immUniformThemeColorShadeAlpha(th_col3, -80, -120); glLineWidth(4.0f); - - glBegin(GL_LINE_STRIP); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); + immVertex2fv(pos, coord_array[i]); } - glEnd(); + + immEnd(); + if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2fv(pos, arrow1); + immVertex2fv(pos, arrow); + immVertex2fv(pos, arrow2); + immEnd(); } } - - /* XXX using GL_LINES for shaded node lines is a workaround - * for Intel hardware, this breaks with GL_LINE_STRIP and - * changing color in begin/end blocks. - */ + glLineWidth(1.5f); - if (do_shaded) { - glBegin(GL_LINES); - for (i = 0; i < LINK_RESOL; i++) { - UI_ThemeColorBlend(th_col1, th_col2, spline_step); - glVertex2fv(coord_array[i]); - - UI_ThemeColorBlend(th_col1, th_col2, spline_step + dist); - glVertex2fv(coord_array[i + 1]); - - spline_step += dist; - } - glEnd(); + + if (drawarrow) { + immUniformThemeColorBlend(th_col1, th_col2, 0.5f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex2fv(pos, arrow1); + immVertex2fv(pos, arrow); + immVertex2fv(pos, arrow2); + immEnd(); } - else { - UI_ThemeColor(th_col1); - glBegin(GL_LINE_STRIP); + + if (!do_shaded) { + immUniformThemeColor(th_col1); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); + immVertex2fv(pos, coord_array[i]); } - glEnd(); + + immEnd(); } - - if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); + + if (do_triple || drawarrow || (!do_shaded)) { + immUnbindProgram(); } - - glDisable(GL_LINE_SMOOTH); - } -} -#if 0 /* not used in 2.5x yet */ -static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2]) -{ - if (link->fromsock) { - coord_array[0][0] = link->fromsock->locx; - coord_array[0][1] = link->fromsock->locy; - } - else { - if (snode == NULL) return; - coord_array[0][0] = snode->mx; - coord_array[0][1] = snode->my; - } - if (link->tosock) { - coord_array[1][0] = link->tosock->locx; - coord_array[1][1] = link->tosock->locy; - } - else { - if (snode == NULL) return; - coord_array[1][0] = snode->mx; - coord_array[1][1] = snode->my; - } -} + if (do_shaded) { + unsigned char col[3]; -void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, - int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3) -{ - float coord_array[2][2]; - int i; - - node_link_straight_points(v2d, snode, link, coord_array); - - glEnable(GL_LINE_SMOOTH); - - if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); - glLineWidth(4.0f); - - glBegin(GL_LINES); - glVertex2fv(coord_array[0]); - glVertex2fv(coord_array[1]); - glEnd(); - } - - UI_ThemeColor(th_col1); - glLineWidth(1.5f); - - /* XXX using GL_LINES for shaded node lines is a workaround - * for Intel hardware, this breaks with GL_LINE_STRIP and - * changing color in begin/end blocks. - */ - if (do_shaded) { - glBegin(GL_LINES); - for (i = 0; i < LINK_RESOL - 1; ++i) { - float t = (float)i / (float)(LINK_RESOL - 1); - UI_ThemeColorBlend(th_col1, th_col2, t); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); - - t = (float)(i + 1) / (float)(LINK_RESOL - 1); - UI_ThemeColorBlend(th_col1, th_col2, t); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); - } - glEnd(); - } - else { - glBegin(GL_LINE_STRIP); - for (i = 0; i < LINK_RESOL; ++i) { - float t = (float)i / (float)(LINK_RESOL - 1); - glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0], - (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]); + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1)); + + for (i = 0; i <= LINK_RESOL; i++) { + UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col); + immAttrib3ubv(color, col); + + immVertex2fv(pos, coord_array[i]); + + spline_step += dist; + } + + immEnd(); + + immUnbindProgram(); } - glEnd(); + + glDisable(GL_LINE_SMOOTH); } - - glDisable(GL_LINE_SMOOTH); } -#endif /* note; this is used for fake links in groups too */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) @@ -3639,27 +3536,27 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } -void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border) +void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos) { - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 4); if (border & (NODE_LEFT | NODE_RIGHT)) { - glVertex2f(cent[0], v2d->cur.ymin); - glVertex2f(cent[0], v2d->cur.ymax); + immVertex2f(pos, cent[0], v2d->cur.ymin); + immVertex2f(pos, cent[0], v2d->cur.ymax); } else { - glVertex2f(cent[0], cent[1] - size); - glVertex2f(cent[0], cent[1] + size); + immVertex2f(pos, cent[0], cent[1] - size); + immVertex2f(pos, cent[0], cent[1] + size); } if (border & (NODE_TOP | NODE_BOTTOM)) { - glVertex2f(v2d->cur.xmin, cent[1]); - glVertex2f(v2d->cur.xmax, cent[1]); + immVertex2f(pos, v2d->cur.xmin, cent[1]); + immVertex2f(pos, v2d->cur.xmax, cent[1]); } else { - glVertex2f(cent[0] - size, cent[1]); - glVertex2f(cent[0] + size, cent[1]); + immVertex2f(pos, cent[0] - size, cent[1]); + immVertex2f(pos, cent[0] + size, cent[1]); } - glEnd(); + immEnd(); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 213e326b1a6..09380977705 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -44,16 +44,21 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" +#include "DEG_depsgraph.h" + #include "BLF_api.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" + #include "WM_api.h" #include "WM_types.h" @@ -128,10 +133,10 @@ void ED_node_tag_update_id(ID *id) * all the users of this tree will have update * flushed from the tree, */ - DAG_id_tag_update(&ntree->id, 0); + DEG_id_tag_update(&ntree->id, 0); if (ntree->type == NTREE_SHADER) { - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); if (GS(id->name) == ID_MA) WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id); @@ -144,12 +149,12 @@ void ED_node_tag_update_id(ID *id) WM_main_add_notifier(NC_SCENE | ND_NODES, id); } else if (ntree->type == NTREE_TEXTURE) { - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); WM_main_add_notifier(NC_TEXTURE | ND_NODES, id); } else if (id == &ntree->id) { /* node groups */ - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); } } @@ -617,103 +622,16 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) glDisable(GL_LINE_SMOOTH); } -static void node_socket_shape_draw( - float x, float y, float size, const float col[4], bool highlight, - const float coords[][2], int coords_len) -{ - int a; - - glColor4fv(col); - - glEnable(GL_BLEND); - glBegin(GL_POLYGON); - for (a = 0; a < coords_len; a++) { - glVertex2f(x + size * coords[a][0], y + size * coords[a][1]); - } - glEnd(); - glDisable(GL_BLEND); - - if (highlight) { - UI_ThemeColor(TH_TEXT_HI); - glLineWidth(1.5f); - } - else { - glColor4ub(0, 0, 0, 150); - } - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); - for (a = 0; a < coords_len; a++) { - glVertex2f(x + size * coords[a][0], y + size * coords[a][1]); - } - glEnd(); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); -} - - -void node_socket_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, bool highlight) +static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col) { - PointerRNA ptr, node_ptr; + PointerRNA ptr; float color[4]; RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); - RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); - - /* 16 values of {sin, cos} function */ - const float shape_circle[16][2] = { - {0.00000000f, 1.00000000f}, - {0.39435585f, 0.91895781f}, - {0.72479278f, 0.68896691f}, - {0.93775213f, 0.34730525f}, - {0.99871650f, -0.05064916f}, - {0.89780453f, -0.44039415f}, - {0.65137248f, -0.75875812f}, - {0.29936312f, -0.95413925f}, - {-0.10116832f, -0.99486932f}, - {-0.48530196f, -0.87434661f}, - {-0.79077573f, -0.61210598f}, - {-0.96807711f, -0.25065253f}, - {-0.98846832f, 0.15142777f}, - {-0.84864425f, 0.52896401f}, - {-0.57126821f, 0.82076344f}, - {-0.20129852f, 0.97952994f } - }; - - const float shape_diamond[4][2] = { - {0.0f, 1.2f}, - {1.2f, 0.0f}, - {0.0f, -1.2f}, - {-1.2f, 0.0f}, - }; - - const float shape_square[4][2] = { - {-0.9f, 0.9f}, - {0.9f, 0.9f}, - {0.9f, -0.9f}, - {-0.9f, -0.9f}, - }; - - const float (*shape)[2]; - int shape_len; - switch (sock->draw_shape) { - default: - case SOCK_DRAW_SHAPE_CIRCLE: - shape = shape_circle; - shape_len = ARRAY_SIZE(shape_circle); - break; - case SOCK_DRAW_SHAPE_DIAMOND: - shape = shape_diamond; - shape_len = ARRAY_SIZE(shape_diamond); - break; - case SOCK_DRAW_SHAPE_SQUARE: - shape = shape_square; - shape_len = ARRAY_SIZE(shape_square); - break; - } - - node_socket_shape_draw(sock->locx, sock->locy, size, color, highlight, shape, shape_len); + + immAttrib4fv(col, color); + immVertex2f(pos, sock->locx, sock->locy); } /* ************** Socket callbacks *********** */ @@ -722,10 +640,15 @@ static void node_draw_preview_background(float tile, rctf *rect) { float x, y; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw checkerboard backdrop to show alpha */ - glColor3ub(120, 120, 120); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); - glColor3ub(160, 160, 160); + immUniformColor3ub(120, 120, 120); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ub(160, 160, 160); for (y = rect->ymin; y < rect->ymax; y += tile * 2) { for (x = rect->xmin; x < rect->xmax; x += tile * 2) { @@ -736,7 +659,7 @@ static void node_draw_preview_background(float tile, rctf *rect) if (y + tile > rect->ymax) tiley = rect->ymax - y; - glRectf(x, y, x + tilex, y + tiley); + immRectf(pos, x, y, x + tilex, y + tiley); } } for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) { @@ -748,9 +671,10 @@ static void node_draw_preview_background(float tile, rctf *rect) if (y + tile > rect->ymax) tiley = rect->ymax - y; - glRectf(x, y, x + tilex, y + tiley); + immRectf(pos, x, y, x + tilex, y + tiley); } } + immUnbindProgram(); } /* not a callback */ @@ -783,15 +707,17 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */ - glColor4f(1.0, 1.0, 1.0, 1.0); - glPixelZoom(scale, scale); - glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); - glPixelZoom(1.0f, 1.0f); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect, + scale, scale, NULL); glDisable(GL_BLEND); - UI_ThemeColorShadeAlpha(TH_BACK, -15, +100); - fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_BACK, -15, +100); + imm_draw_line_box_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); + immUnbindProgram(); } /* common handle function for operator buttons that need to select the node first */ @@ -816,23 +742,134 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) else { const float margin = 3.0f; - glColor4f(0.0f, 0.0f, 0.0f, 0.33f); - glEnable(GL_BLEND); - UI_draw_roundbox(rct->xmin - margin, rct->ymin - margin, - rct->xmax + margin, rct->ymax + margin, radius + margin); - glDisable(GL_BLEND); + float color[4] = {0.0f, 0.0f, 0.0f, 0.33f}; + UI_draw_roundbox_aa(true, rct->xmin - margin, rct->ymin - margin, + rct->xmax + margin, rct->ymax + margin, radius + margin, color); + } +} + +void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all) +{ + const unsigned int total_input_ct = BLI_listbase_count(&node->inputs); + const unsigned int total_output_ct = BLI_listbase_count(&node->outputs); + + if (total_input_ct + total_output_ct == 0) { + return; + } + + PointerRNA node_ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + + float scale; + UI_view2d_scale_get(v2d, &scale, NULL); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + glEnable(GL_BLEND); + GPU_enable_program_point_size(); + + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA); + + /* set handle size */ + immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */ + + if (!select_all) { + /* outline for unselected sockets */ + immUniform1f("outlineWidth", 1.0f); + immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f); + + immBeginAtMost(GWN_PRIM_POINTS, total_input_ct + total_output_ct); + } + + /* socket inputs */ + short selected_input_ct = 0; + bNodeSocket *sock; + for (sock = node->inputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + ++selected_input_ct; + continue; + } + + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + } + + /* socket outputs */ + short selected_output_ct = 0; + if (draw_outputs) { + for (sock = node->outputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + ++selected_output_ct; + continue; + } + + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + } + } + + if (!select_all) { + immEnd(); + } + + /* go back and draw selected sockets */ + if (selected_input_ct + selected_output_ct > 0) { + /* outline for selected sockets */ + float c[3]; + UI_GetThemeColor3fv(TH_TEXT_HI, c); + immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f); + immUniform1f("outlineWidth", 1.5f); + + immBegin(GWN_PRIM_POINTS, selected_input_ct + selected_output_ct); + + if (selected_input_ct) { + /* socket inputs */ + for (sock = node->inputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + if (--selected_input_ct == 0) + break; /* stop as soon as last one is drawn */ + } + } + } + + if (selected_output_ct) { + /* socket outputs */ + for (sock = node->outputs.first; sock; sock = sock->next) { + if (nodeSocketIsHidden(sock)) + continue; + if (select_all || (sock->flag & SELECT)) { + node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + if (--selected_output_ct == 0) + break; /* stop as soon as last one is drawn */ + } + } + } + + immEnd(); } + + immUnbindProgram(); + + GPU_disable_program_point_size(); + glDisable(GL_BLEND); } static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data; - bNodeSocket *sock; rctf *rct = &node->totr; float iconofs; /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; int color_id = node_get_colorid(node); + float color[4]; char showname[128]; /* 128 used below */ View2D *v2d = &ar->v2d; @@ -841,7 +878,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN nodeSynchronizeID(node, false); /* skip if out of view */ - if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) { + if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) { UI_block_end(C, node->block); node->block = NULL; return; @@ -850,23 +887,24 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* shadow */ node_draw_shadow(snode, node, BASIS_RAD, 1.0f); - /* header uses color from backdrop, but we make it opaqie */ - if (color_id == TH_NODE) { - float col[3]; - UI_GetThemeColorShade3fv(color_id, -20, col); - glColor4f(col[0], col[1], col[2], 1.0f); + if (node->flag & NODE_MUTED) { + UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color); + } + else { + /* header uses color from backdrop, but we make it opaque */ + if (color_id == TH_NODE) { + UI_GetThemeColorShade3fv(color_id, -20, color); + color[3] = 1.0f; + } + else { + UI_GetThemeColor4fv(color_id, color); + } } - else - UI_ThemeColor(color_id); - - if (node->flag & NODE_MUTED) - UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); - glLineWidth(1.0f); UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); - UI_draw_roundbox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color); /* show/hide icons */ iconofs = rct->xmax - 0.35f * U.widget_unit; @@ -899,10 +937,12 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN } /* title */ - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + if (node->flag & SELECT) { + UI_GetThemeColor4fv(TH_SELECT, color); + } + else { + UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color); + } /* open/close entirely? */ { @@ -917,17 +957,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_block_emboss_set(node->block, UI_EMBOSS); /* custom draw function for this button */ - UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v'); + UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color); } - /* this isn't doing anything for the label, so commenting out */ -#if 0 - if (node->flag & SELECT) - UI_ThemeColor(TH_TEXT_HI); - else - UI_ThemeColor(TH_TEXT); -#endif - nodeLabel(ntree, node, showname, sizeof(showname)); //if (node->flag & NODE_MUTED) @@ -940,55 +972,30 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* body */ if (!nodeIsRegistered(node)) - UI_ThemeColor4(TH_REDALERT); /* use warning color to indicate undefined types */ - else if (node->flag & NODE_CUSTOM_COLOR) - glColor3fv(node->color); + UI_GetThemeColor4fv(TH_REDALERT, color); /* use warning color to indicate undefined types */ + else if (node->flag & NODE_CUSTOM_COLOR) { + rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f); + } else - UI_ThemeColor4(TH_NODE); - glEnable(GL_BLEND); + UI_GetThemeColor4fv(TH_NODE, color); + UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - + UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); + UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); } /* disable lines */ if (node->flag & NODE_MUTED) node_draw_mute_line(v2d, snode, node); - - /* socket inputs, buttons */ - for (sock = node->inputs.first; sock; sock = sock->next) { - if (nodeSocketIsHidden(sock)) - continue; - - node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); - } - - /* socket outputs */ - for (sock = node->outputs.first; sock; sock = sock->next) { - if (nodeSocketIsHidden(sock)) - continue; - - node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT); - } - + node_draw_sockets(v2d, C, ntree, node, true, false); + /* preview */ if (node->flag & NODE_PREVIEW && previews) { bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key); @@ -1008,37 +1015,33 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) { - bNodeSocket *sock; rctf *rct = &node->totr; float dx, centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - float socket_size = NODE_SOCKSIZE; int color_id = node_get_colorid(node); + float color[4]; char showname[128]; /* 128 is used below */ + View2D *v2d = &ar->v2d; + float scale; + + UI_view2d_scale_get(v2d, &scale, NULL); /* shadow */ node_draw_shadow(snode, node, hiddenrad, 1.0f); /* body */ - UI_ThemeColor(color_id); if (node->flag & NODE_MUTED) - UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); - - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); + UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color); + else + UI_GetThemeColor4fv(color_id, color); + + UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - if (node->flag & NODE_ACTIVE) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); - else - UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); - - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); + + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); } /* custom color inline */ @@ -1046,18 +1049,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3fv(node->color); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad); + UI_draw_roundbox_3fvAlpha(false, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad, node->color, 1.0f); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } /* title */ - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); + if (node->flag & SELECT) { + UI_GetThemeColor4fv(TH_SELECT, color); + } + else { + UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color); + } /* open entirely icon */ { @@ -1072,18 +1076,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b UI_block_emboss_set(node->block, UI_EMBOSS); /* custom draw function for this button */ - UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h'); + UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h', color); } /* disable lines */ if (node->flag & NODE_MUTED) node_draw_mute_line(&ar->v2d, snode, node); - - if (node->flag & SELECT) - UI_ThemeColor(TH_SELECT); - else - UI_ThemeColor(TH_TEXT); - + if (node->miniwidth > 0.0f) { nodeLabel(ntree, node, showname, sizeof(showname)); @@ -1097,29 +1096,35 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b } /* scale widget thing */ - UI_ThemeColorShade(color_id, -10); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColorShade(color_id, -10); dx = 10.0f; - fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f); - fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); - - UI_ThemeColorShade(color_id, +30); + + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rct->xmax - dx, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx, centy + 4.0f); + + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immEnd(); + + immUniformThemeColorShade(color_id, 30); dx -= snode->aspect; - fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f); - fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); - /* sockets */ - for (sock = node->inputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); - } - } - - for (sock = node->outputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); - } - } - + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rct->xmax - dx, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx, centy + 4.0f); + + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immEnd(); + + immUnbindProgram(); + + node_draw_sockets(v2d, C, ntree, node, true, false); + UI_block_end(C, node->block); UI_block_draw(C, node->block); node->block = NULL; @@ -1260,7 +1265,7 @@ static void draw_tree_path(SpaceNode *snode) ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info)); - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info)); } @@ -1293,12 +1298,14 @@ static void draw_group_overlay(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; rctf rect = v2d->cur; uiBlock *block; - + float color[4]; + /* shade node groups to separate them visually */ - UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); glEnable(GL_BLEND); + + UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color); UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0); + UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); glDisable(GL_BLEND); /* set the block bounds to clip mouse events from underlying nodes */ @@ -1330,7 +1337,6 @@ void drawnodespace(const bContext *C, ARegion *ar) /* only set once */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_MAP1_VERTEX_3); /* nodes */ snode_set_context(C); @@ -1390,7 +1396,23 @@ void drawnodespace(const bContext *C, ARegion *ar) /* backdrop */ draw_nodespace_back_pix(C, ar, snode, path->parent_key); - + + { + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); + + gpuPushMatrix(); + gpuLoadIdentity(); + + glaDefine2DArea(&ar->winrct); + wmOrtho2_pixelspace(ar->winx, ar->winy); + + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); + } + draw_nodetree(C, ar, ntree, path->parent_key); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index e91fd1ee575..a8bf68d92e2 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -41,7 +41,6 @@ #include "BLI_blenlib.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_library.h" @@ -50,6 +49,8 @@ #include "BKE_report.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "RE_engine.h" #include "RE_pipeline.h" @@ -123,7 +124,7 @@ static int compo_get_recalc_flags(const bContext *C) int recalc_flags = 0; for (win = wm->windows.first; win; win = win->next) { - bScreen *sc = win->screen; + const bScreen *sc = WM_window_get_active_screen(win); ScrArea *sa; for (sa = sc->areabase.first; sa; sa = sa->next) { @@ -328,11 +329,11 @@ void snode_dag_update(bContext *C, SpaceNode *snode) if (snode->edittree != snode->nodetree) { FOREACH_NODETREE(bmain, tntree, id) { if (ntreeHasTree(tntree, snode->edittree)) - DAG_id_tag_update(id, 0); + DEG_id_tag_update(id, 0); } FOREACH_NODETREE_END } - DAG_id_tag_update(snode->id, 0); + DEG_id_tag_update(snode->id, 0); } void snode_notify(bContext *C, SpaceNode *snode) @@ -397,7 +398,11 @@ void ED_node_shader_default(const bContext *C, ID *id) Material *ma = (Material *)id; ma->nodetree = ntree; - if (BKE_scene_use_new_shading_nodes(scene)) { + if (BKE_scene_uses_blender_eevee(scene)) { + output_type = SH_NODE_OUTPUT_MATERIAL; + shader_type = SH_NODE_BSDF_PRINCIPLED; + } + else if (BKE_scene_use_new_shading_nodes(scene)) { output_type = SH_NODE_OUTPUT_MATERIAL; shader_type = SH_NODE_BSDF_DIFFUSE; } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 352f9e51012..12e3c33007e 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -67,13 +67,11 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transfo /* node_draw.c */ int node_get_colorid(struct bNode *node); -void node_socket_draw( - const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, - struct bNodeSocket *sock, float size, bool highlight); int node_get_resize_cursor(int directions); void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); +void node_draw_sockets(struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, bool draw_outputs, bool select_all); void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); @@ -221,6 +219,13 @@ void NODE_OT_shader_script_update(struct wmOperatorType *ot); void NODE_OT_viewer_border(struct wmOperatorType *ot); void NODE_OT_clear_viewer_border(struct wmOperatorType *ot); +/* node_widgets.c */ +void NODE_WGT_backdrop_transform(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_crop(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_sun_beams(struct wmManipulatorGroupType *wgt); +void NODE_WGT_backdrop_corner_pin(struct wmManipulatorGroupType *wgt); + + extern const char *node_context_dir[]; // XXXXXX diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c new file mode 100644 index 00000000000..8e736e47963 --- /dev/null +++ b/source/blender/editors/space_node/node_manipulators.c @@ -0,0 +1,614 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_node/node_manipulators.c + * \ingroup spnode + */ + +#include <math.h> + +#include "BKE_context.h" +#include "BKE_image.h" + +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "IMB_imbuf_types.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "node_intern.h" + + +/* -------------------------------------------------------------------- */ + +/** \name Local Utilities + * \{ */ + +static void node_manipulator_calc_matrix_space( + const SpaceNode *snode, const ARegion *ar, float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom); + mul_v3_fl(matrix_space[1], snode->zoom); + matrix_space[3][0] = (ar->winx / 2) + snode->xof; + matrix_space[3][1] = (ar->winy / 2) + snode->yof; +} + +static void node_manipulator_calc_matrix_space_with_image_dims( + const SpaceNode *snode, const ARegion *ar, const float image_dims[2], float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]); + mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]); + matrix_space[3][0] = ((ar->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom); + matrix_space[3][1] = ((ar->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom); +} + +/** \} */ + + + +/* -------------------------------------------------------------------- */ + +/** \name Backdrop Manipulator + * \{ */ + +static void manipulator_node_backdrop_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + const SpaceNode *snode = mpr_prop->custom_func.user_data; + matrix[0][0] = snode->zoom; + matrix[1][1] = snode->zoom; + matrix[3][0] = snode->xof; + matrix[3][1] = snode->yof; +} + +static void manipulator_node_backdrop_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + SpaceNode *snode = mpr_prop->custom_func.user_data; + snode->zoom = matrix[0][0]; + snode->zoom = matrix[1][1]; + snode->xof = matrix[3][0]; + snode->yof = matrix[3][1]; +} + +static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(wwrapper->manipulator->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + mgroup->customdata = wwrapper; +} + +static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulator *cage = ((wmManipulatorWrapper *)mgroup->customdata)->manipulator; + const ARegion *ar = CTX_wm_region(C); + /* center is always at the origin */ + const float origin[3] = {ar->winx / 2, ar->winy / 2}; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + const float dims[2] = { + (ibuf->x > 0) ? ibuf->x : 64.0f, + (ibuf->y > 0) ? ibuf->y : 64.0f, + }; + + RNA_float_set_array(cage->ptr, "dimensions", dims); + WM_manipulator_set_matrix_location(cage, origin); + WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, false); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + SpaceNode *snode = CTX_wm_space_node(C); +#if 0 + PointerRNA nodeptr; + RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr); + WM_manipulator_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1); + WM_manipulator_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1); +#endif + + WM_manipulator_target_property_def_func( + cage, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_backdrop_prop_matrix_get, + .value_set_fn = manipulator_node_backdrop_prop_matrix_set, + .range_get_fn = NULL, + .user_data = snode, + }); + } + else { + WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_transform(wmManipulatorGroupType *wgt) +{ + wgt->name = "Backdrop Transform Widget"; + wgt->idname = "NODE_WGT_backdrop_transform"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_transform_poll; + wgt->setup = WIDGETGROUP_node_transform_setup; + wgt->refresh = WIDGETGROUP_node_transform_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Crop Manipulator + * \{ */ + +struct NodeCropWidgetGroup { + wmManipulator *border; + + struct { + float dims[2]; + } state; + + struct { + PointerRNA ptr; + PropertyRNA *prop; + bContext *context; + } update_data; +}; + +static void manipulator_node_crop_update(struct NodeCropWidgetGroup *crop_group) +{ + RNA_property_update(crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop); +} + +static void two_xy_to_rect(const NodeTwoXYs *nxy, rctf *rect, const float dims[2], bool is_relative) +{ + if (is_relative) { + rect->xmin = nxy->fac_x1; + rect->xmax = nxy->fac_x2; + rect->ymin = nxy->fac_y1; + rect->ymax = nxy->fac_y2; + } + else { + rect->xmin = nxy->x1 / dims[0]; + rect->xmax = nxy->x2 / dims[0]; + rect->ymin = nxy->y1 / dims[1]; + rect->ymax = nxy->y2 / dims[1]; + } +} + +static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, const float dims[2], bool is_relative) +{ + if (is_relative) { + nxy->fac_x1 = rect->xmin; + nxy->fac_x2 = rect->xmax; + nxy->fac_y1 = rect->ymin; + nxy->fac_y2 = rect->ymax; + } + else { + nxy->x1 = rect->xmin * dims[0]; + nxy->x2 = rect->xmax * dims[0]; + nxy->y1 = rect->ymin * dims[1]; + nxy->y2 = rect->ymax * dims[1]; + } +} + +/* scale callbacks */ +static void manipulator_node_crop_prop_matrix_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + const bNode *node = mpr_prop->custom_func.user_data; + const NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + matrix[0][0] = BLI_rctf_size_x(&rct); + matrix[1][1] = BLI_rctf_size_y(&rct); + matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0]; + matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1]; +} + +static void manipulator_node_crop_prop_matrix_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + bNode *node = mpr_prop->custom_func.user_data; + NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + BLI_rctf_resize(&rct, matrix[0][0], matrix[1][1]); + BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, &rct, &rct); + two_xy_from_rect(nxy, &rct, dims, is_relative); + manipulator_node_crop_update(crop_group); +} + +static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CROP)) { + /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */ + if ((node->custom1 & (0 << 1)) == 0) { + return true; + } + } + } + + return false; +} + +static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__); + + crop_group->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(crop_group->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = crop_group; +} + +static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + ARegion *ar = CTX_wm_region(C); + wmManipulator *mpr = mgroup->manipulators.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_manipulator_calc_matrix_space(snode, ar, mpr->matrix_space); +} + +static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = mgroup->customdata; + wmManipulator *mpr = crop_group->border; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + RNA_float_set_array(mpr->ptr, "dimensions", crop_group->state.dims); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + crop_group->update_data.context = (bContext *)C; + RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr); + crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, "relative"); + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_crop_prop_matrix_get, + .value_set_fn = manipulator_node_crop_prop_matrix_set, + .range_get_fn = NULL, + .user_data = node, + }); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_crop(wmManipulatorGroupType *wgt) +{ + wgt->name = "Backdrop Crop Widget"; + wgt->idname = "NODE_WGT_backdrop_crop"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_crop_poll; + wgt->setup = WIDGETGROUP_node_crop_setup; + wgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare; + wgt->refresh = WIDGETGROUP_node_crop_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Sun Beams + * \{ */ + +struct NodeSunBeamsWidgetGroup { + wmManipulator *manipulator; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), __func__); + + sbeam_group->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL); + wmManipulator *mpr = sbeam_group->manipulator; + + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D); + + mpr->scale_basis = 0.05f; + + mgroup->customdata = sbeam_group; +} + +static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; + ARegion *ar = CTX_wm_region(C); + wmManipulator *mpr = mgroup->manipulators.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_manipulator_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, mpr->matrix_space); +} + +static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; + wmManipulator *mpr = sbeam_group->manipulator; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA nodeptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &nodeptr, "source", -1); + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_sun_beams(wmManipulatorGroupType *wgt) +{ + wgt->name = "Sun Beams Widget"; + wgt->idname = "NODE_WGT_sbeam"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_sbeam_poll; + wgt->setup = WIDGETGROUP_node_sbeam_setup; + wgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare; + wgt->refresh = WIDGETGROUP_node_sbeam_refresh; +} + +/** \} */ + + + +/* -------------------------------------------------------------------- */ + +/** \name Corner Pin + * \{ */ + +struct NodeCornerPinWidgetGroup { + wmManipulator *manipulators[4]; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(sizeof(struct NodeCornerPinWidgetGroup), __func__); + const wmManipulatorType *wt_grab_3d = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", false); + + for (int i = 0; i < 4; i++) { + cpin_group->manipulators[i] = WM_manipulator_new_ptr(wt_grab_3d, mgroup, NULL); + wmManipulator *mpr = cpin_group->manipulators[i]; + + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D); + + mpr->scale_basis = 0.01f; + } + + mgroup->customdata = cpin_group; +} + +static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; + ARegion *ar = CTX_wm_region(C); + + SpaceNode *snode = CTX_wm_space_node(C); + + float matrix_space[4][4]; + node_manipulator_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space); + + for (int i = 0; i < 4; i++) { + wmManipulator *mpr = cpin_group->manipulators[i]; + copy_m4_m4(mpr->matrix_space, matrix_space); + } +} + +static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; + + void *lock; + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + int i = 0; + for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) { + if (sock->type == SOCK_VECTOR) { + wmManipulator *mpr = cpin_group->manipulators[i++]; + + PointerRNA sockptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &sockptr, "default_value", -1); + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true); + } + } + } + else { + for (int i = 0; i < 4; i++) { + wmManipulator *mpr = cpin_group->manipulators[i]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_corner_pin(wmManipulatorGroupType *wgt) +{ + wgt->name = "Corner Pin Widget"; + wgt->idname = "NODE_WGT_backdrop_corner_pin"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_corner_pin_poll; + wgt->setup = WIDGETGROUP_node_corner_pin_setup; + wgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare; + wgt->refresh = WIDGETGROUP_node_corner_pin_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 2267316d257..af71851cf64 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -57,6 +57,8 @@ #include "RNA_access.h" +#include "WM_api.h" + #include "node_intern.h" /* own include */ @@ -381,12 +383,12 @@ static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) } -static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) +static void node_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, const Scene *scene) { /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = sa->spacedata.first; /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ - short shader_type = BKE_scene_use_new_shading_nodes(sc->scene) ? snode->shaderfrom : SNODE_SHADER_OBJECT; + short shader_type = BKE_scene_use_new_shading_nodes(scene) ? snode->shaderfrom : SNODE_SHADER_OBJECT; /* preview renders */ switch (wmn->category) { @@ -643,6 +645,14 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); + /* manipulators stay in the background for now - quick patchjob to make sure nodes themselves work */ + if (ar->manipulator_map == NULL) { + ar->manipulator_map = WM_manipulatormap_new_from_type( + &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW}); + } + + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* own keymaps */ keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); @@ -737,18 +747,32 @@ static void node_header_region_draw(const bContext *C, ARegion *ar) } /* used for header + main region */ -static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void node_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { + wmManipulatorMap *mmap = ar->manipulator_map; + /* context changes */ switch (wmn->category) { case NC_SPACE: - if (wmn->data == ND_SPACE_NODE) - ED_region_tag_redraw(ar); + switch (wmn->data) { + case ND_SPACE_NODE: + ED_region_tag_redraw(ar); + break; + case ND_SPACE_NODE_VIEW: + WM_manipulatormap_tag_refresh(mmap); + break; + } break; case NC_SCREEN: + if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) { + WM_manipulatormap_tag_refresh(mmap); + } switch (wmn->data) { case ND_SCREENCAST: case ND_ANIMPLAY: + case ND_LAYER: ED_region_tag_redraw(ar); break; } @@ -758,10 +782,20 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi ED_region_tag_redraw(ar); break; case NC_SCENE: + ED_region_tag_redraw(ar); + if (wmn->data == ND_RENDER_RESULT) { + WM_manipulatormap_tag_refresh(mmap); + } + break; + case NC_NODE: + ED_region_tag_redraw(ar); + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + WM_manipulatormap_tag_refresh(mmap); + } + break; case NC_MATERIAL: case NC_TEXTURE: case NC_WORLD: - case NC_NODE: case NC_LINESTYLE: ED_region_tag_redraw(ar); break; @@ -826,6 +860,17 @@ static int node_context(const bContext *C, const char *member, bContextDataResul return 0; } +static void node_widgets(void) +{ + /* create the widgetmap for the area here */ + wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure( + &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW}); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_transform); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_crop); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_sun_beams); + WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_corner_pin); +} + static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id) { SpaceNode *snode = (SpaceNode *)slink; @@ -916,6 +961,7 @@ void ED_spacetype_node(void) st->refresh = node_area_refresh; st->context = node_context; st->dropboxes = node_dropboxes; + st->manipulators = node_widgets; st->id_remap = node_id_remap; /* regions: main window */ |