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 | 757 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_add.c | 14 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_buttons.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 521 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 113 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 18 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_manipulators.c | 621 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.c | 13 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_templates.c | 13 | ||||
-rw-r--r-- | source/blender/editors/space_node/space_node.c | 101 |
12 files changed, 1395 insertions, 784 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 fff6c5d9f2c..12da5086c52 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -50,9 +50,14 @@ #include "BLF_api.h" #include "BLT_translation.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" +#include "GPU_state.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -62,6 +67,7 @@ #include "WM_types.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" @@ -80,49 +86,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 +355,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 +364,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 +430,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,38 +440,30 @@ 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); + UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); } /* label */ @@ -580,15 +537,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,26 +553,29 @@ 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); + GPU_blend(true); + GPU_line_smooth(true); /* 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); + GPU_line_smooth(false); + GPU_blend(false); } #endif @@ -637,9 +591,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); @@ -728,21 +680,6 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr, } } -static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr) -{ - bNode *node = ptr->data; - uiLayout *col; - - uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL); - - if (!node->id) return; - - col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_diffuse", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_specular", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "invert_normal", 0, NULL, ICON_NONE); -} - static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *row, *col, *sub; @@ -790,30 +727,6 @@ static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE); } -static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA *ptr) -{ - PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); - uiLayout *col; - - col = uiLayoutColumn(layout, false); - - 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, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE); - } - else { - uiItemR(col, ptr, "uv_layer", 0, IFACE_("UV"), ICON_NONE); - uiItemR(col, ptr, "color_layer", 0, IFACE_("VCol"), ICON_NONE); - } -} - -static void node_shader_buts_lamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "lamp_object", 0, IFACE_("Lamp Object"), ICON_NONE); -} - static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE); @@ -1022,7 +935,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); } } } @@ -1041,7 +954,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); @@ -1068,7 +981,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); @@ -1179,13 +1092,6 @@ static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSE static void node_shader_set_butfunc(bNodeType *ntype) { switch (ntype->type) { - case SH_NODE_MATERIAL: - case SH_NODE_MATERIAL_EXT: - ntype->draw_buttons = node_shader_buts_material; - break; - case SH_NODE_TEXTURE: - ntype->draw_buttons = node_buts_texture; - break; case SH_NODE_NORMAL: ntype->draw_buttons = node_buts_normal; break; @@ -1219,12 +1125,6 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_VECT_TRANSFORM: ntype->draw_buttons = node_shader_buts_vect_transform; break; - case SH_NODE_GEOMETRY: - ntype->draw_buttons = node_shader_buts_geometry; - break; - case SH_NODE_LAMP: - ntype->draw_buttons = node_shader_buts_lamp; - break; case SH_NODE_ATTRIBUTE: ntype->draw_buttons = node_shader_buts_attribute; break; @@ -1373,7 +1273,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1); } -static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; uiLayout *col, *row; @@ -2271,14 +2171,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(); } } @@ -2297,9 +2204,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; @@ -2312,12 +2216,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) @@ -2335,9 +2248,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; @@ -2350,13 +2260,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); + + immBegin(GWN_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x3, y3); + immVertex2f(pos, x4, y4); + immEnd(); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glVertex2f(x3, y3); - glVertex2f(x4, y4); - glEnd(); + immUnbindProgram(); } static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2556,7 +2474,7 @@ static void node_composit_set_butfunc(bNodeType *ntype) ntype->draw_buttons_ex = node_composit_buts_image_ex; break; case CMP_NODE_R_LAYERS: - ntype->draw_buttons = node_composit_buts_renderlayers; + ntype->draw_buttons = node_composit_buts_viewlayers; break; case CMP_NODE_NORMAL: ntype->draw_buttons = node_buts_normal; @@ -3246,6 +3164,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b { Main *bmain = CTX_data_main(C); 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; @@ -3261,14 +3180,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b 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); wmOrtho2_region_pixelspace(ar); x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof; @@ -3278,60 +3193,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; + if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) { 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 - - 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)); + 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; - glPixelZoom(1.0f, 1.0f); - } - else if (snode->flag & SNODE_SHOW_ALPHA) { - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + 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); - 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); + immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, + display_buffer, snode->zoom, snode->zoom, NULL); -#ifdef __BIG_ENDIAN__ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); -#endif - glPixelZoom(1.0f, 1.0f); + 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); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom); - glPixelZoom(1.0f, 1.0f); - glDisable(GL_BLEND); + GPU_blend(false); } 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) @@ -3356,30 +3248,33 @@ 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); } - -/* if v2d not NULL, it clips and returns 0 if not visible */ -bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) +/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */ +static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *link, float vec[4][2]) { - float dist, vec[4][2]; + float dist; float deltax, deltay; float cursor[2] = {0.0f, 0.0f}; int toreroute, fromreroute; @@ -3447,13 +3342,23 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo vec[2][0] = vec[3][0] - dist; vec[2][1] = vec[3][1]; } + if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) { - /* clipped */ + return 0; /* clipped */ } else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) { - /* clipped */ + return 0; /* clipped */ } - else { + + return 1; +} + +/* if v2d not NULL, it clips and returns 0 if not visible */ +bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) +{ + float vec[4][2]; + + if (node_link_bezier_handles(v2d, snode, link, vec)) { /* always do all three, to prevent data hanging around */ BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0] + 0, resol, sizeof(float) * 2); @@ -3465,186 +3370,242 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo return 0; } +#define NODELINK_GROUP_SIZE 256 #define LINK_RESOL 24 -#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */ -#define ARROW_SIZE (7 * UI_DPI_FAC) -void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, - int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3) -{ - float coord_array[LINK_RESOL + 1][2]; - - if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) { - float dist, spline_step = 0.0f; - int i; - int drawarrow; - /* store current linewidth */ - float linew; - float arrow[2], arrow1[2], arrow2[2]; - glGetFloatv(GL_LINE_WIDTH, &linew); - - /* we can reuse the dist variable here to increment the GL curve eval amount*/ - dist = 1.0f / (float)LINK_RESOL; - - glEnable(GL_LINE_SMOOTH); - - drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && - (link->fromnode && (link->fromnode->type == NODE_REROUTE))); - - if (drawarrow) { - /* draw arrow in line segment LINK_ARROW */ - float d_xy[2], len; - - sub_v2_v2v2(d_xy, coord_array[LINK_ARROW], coord_array[LINK_ARROW - 1]); - len = len_v2(d_xy); - mul_v2_fl(d_xy, ARROW_SIZE / len); - arrow1[0] = coord_array[LINK_ARROW][0] - d_xy[0] + d_xy[1]; - arrow1[1] = coord_array[LINK_ARROW][1] - d_xy[1] - d_xy[0]; - arrow2[0] = coord_array[LINK_ARROW][0] - d_xy[0] - d_xy[1]; - arrow2[1] = coord_array[LINK_ARROW][1] - d_xy[1] + d_xy[0]; - arrow[0] = coord_array[LINK_ARROW][0]; - arrow[1] = coord_array[LINK_ARROW][1]; +#define LINK_WIDTH (2.5f * UI_DPI_FAC) +#define ARROW_SIZE (7 * UI_DPI_FAC) + +static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}}; +static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}}; + +struct { + Gwn_Batch *batch; /* for batching line together */ + Gwn_Batch *batch_single; /* for single line */ + Gwn_VertBuf *inst_vbo; + unsigned int p0_id, p1_id, p2_id, p3_id; + unsigned int colid_id; + Gwn_VertBufRaw p0_step, p1_step, p2_step, p3_step; + Gwn_VertBufRaw colid_step; + unsigned int count; + bool enabled; +} g_batch_link = {0}; + +static void nodelink_batch_reset(void) +{ + GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step); + GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step); + GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step); + GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step); + GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step); + g_batch_link.count = 0; +} + +static void set_nodelink_vertex( + Gwn_VertBuf *vbo, + unsigned int uv_id, unsigned int pos_id, unsigned int exp_id, unsigned int v, + const unsigned char uv[2], const float pos[2], const float exp[2]) +{ + GWN_vertbuf_attr_set(vbo, uv_id, v, uv); + GWN_vertbuf_attr_set(vbo, pos_id, v, pos); + GWN_vertbuf_attr_set(vbo, exp_id, v, exp); +} + +static void nodelink_batch_init(void) +{ + Gwn_VertFormat format = {0}; + unsigned int uv_id = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int expand_id = GWN_vertformat_attr_add(&format, "expand", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC); + int vcount = LINK_RESOL * 2; /* curve */ + vcount += 2; /* restart strip */ + vcount += 3 * 2; /* arrow */ + vcount *= 2; /* shadow */ + vcount += 2; /* restart strip */ + GWN_vertbuf_data_alloc(vbo, vcount); + int v = 0; + + for (int k = 0; k < 2; ++k) { + unsigned char uv[2] = {0, 0}; + float pos[2] = {0.0f, 0.0f}; + float exp[2] = {0.0f, 1.0f}; + + /* restart */ + if (k == 1) + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + + /* curve strip */ + for (int i = 0; i < LINK_RESOL; ++i) { + uv[0] = 255 * (i / (float)(LINK_RESOL - 1)); + uv[1] = 0; + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + uv[1] = 255; + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); } - if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); - glLineWidth(4.0f); - - glBegin(GL_LINE_STRIP); - for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); - } - glEnd(); - if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); - } + /* restart */ + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + + uv[0] = 127; + uv[1] = 0; + copy_v2_v2(pos, arrow_verts[0]); + copy_v2_v2(exp, arrow_expand_axis[0]); + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + /* arrow */ + for (int i = 0; i < 3; ++i) { + uv[1] = 0; + copy_v2_v2(pos, arrow_verts[i]); + copy_v2_v2(exp, arrow_expand_axis[i]); + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + + uv[1] = 255; + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); } - /* 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(); - } - else { - UI_ThemeColor(th_col1); - glBegin(GL_LINE_STRIP); - for (i = 0; i <= LINK_RESOL; i++) { - glVertex2fv(coord_array[i]); - } - glEnd(); - } + /* restart */ + if (k == 0) + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + } - if (drawarrow) { - glBegin(GL_LINE_STRIP); - glVertex2fv(arrow1); - glVertex2fv(arrow); - glVertex2fv(arrow2); - glEnd(); - } + g_batch_link.batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_batch_link.batch); - glDisable(GL_LINE_SMOOTH); - } + g_batch_link.batch_single = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, 0); + gpu_batch_presets_register(g_batch_link.batch_single); + + /* Instances data */ + Gwn_VertFormat format_inst = {0}; + g_batch_link.p0_id = GWN_vertformat_attr_add(&format_inst, "P0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + g_batch_link.p1_id = GWN_vertformat_attr_add(&format_inst, "P1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + g_batch_link.p2_id = GWN_vertformat_attr_add(&format_inst, "P2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + g_batch_link.p3_id = GWN_vertformat_attr_add(&format_inst, "P3", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + g_batch_link.colid_id = GWN_vertformat_attr_add(&format_inst, "colid_doarrow", GWN_COMP_U8, 4, GWN_FETCH_INT); + g_batch_link.inst_vbo = GWN_vertbuf_create_with_format_ex(&format_inst, GWN_USAGE_STREAM); + GWN_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */ + + GWN_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true); + + nodelink_batch_reset(); } -#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]) +static char nodelink_get_color_id(int th_col) { - 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; + switch (th_col) { + case TH_WIRE: return 1; + case TH_WIRE_INNER: return 2; + case TH_ACTIVE: return 3; + case TH_EDGE_SELECT: return 4; + case TH_REDALERT: return 5; } + return 0; +} + +static void nodelink_batch_draw(SpaceNode *snode) +{ + if (g_batch_link.count == 0) + return; + + GPU_blend(true); + + float colors[6][4] = {{0.0f}}; + UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]); + UI_GetThemeColor4fv(TH_WIRE, colors[nodelink_get_color_id(TH_WIRE)]); + UI_GetThemeColor4fv(TH_ACTIVE, colors[nodelink_get_color_id(TH_ACTIVE)]); + UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]); + UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]); + + GWN_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count); + GWN_vertbuf_use(g_batch_link.inst_vbo); /* force update. */ + + GWN_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST); + GWN_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors); + GWN_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH); + GWN_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE); + GWN_batch_draw(g_batch_link.batch); + + nodelink_batch_reset(); + + GPU_blend(false); } -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) +void nodelink_batch_start(SpaceNode *UNUSED(snode)) { - float coord_array[2][2]; - int i; + g_batch_link.enabled = true; +} - node_link_straight_points(v2d, snode, link, coord_array); +void nodelink_batch_end(SpaceNode *snode) +{ + nodelink_batch_draw(snode); + g_batch_link.enabled = false; +} - glEnable(GL_LINE_SMOOTH); +static void nodelink_batch_add_link( + SpaceNode *snode, + const float p0[2], const float p1[2], const float p2[2], const float p3[2], + int th_col1, int th_col2, int th_col3, bool drawarrow) +{ + /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */ + BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); + BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); + BLI_assert(ELEM(th_col3, TH_WIRE, -1)); - if (do_triple) { - UI_ThemeColorShadeAlpha(th_col3, -80, -120); - glLineWidth(4.0f); + g_batch_link.count++; + copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p0_step), p0); + copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p1_step), p1); + copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p2_step), p2); + copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p3_step), p3); + char *colid = GWN_vertbuf_raw_step(&g_batch_link.colid_step); + colid[0] = nodelink_get_color_id(th_col1); + colid[1] = nodelink_get_color_id(th_col2); + colid[2] = nodelink_get_color_id(th_col3); + colid[3] = drawarrow; - glBegin(GL_LINES); - glVertex2fv(coord_array[0]); - glVertex2fv(coord_array[1]); - glEnd(); + if (g_batch_link.count == NODELINK_GROUP_SIZE) { + nodelink_batch_draw(snode); } +} - UI_ThemeColor(th_col1); - glLineWidth(1.5f); +/* don't do shadows if th_col3 is -1. */ +void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, + int th_col1, int th_col2, int th_col3) +{ + float vec[4][2]; - /* 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]); + if (node_link_bezier_handles(v2d, snode, link, vec)) { + int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && + (link->fromnode && (link->fromnode->type == NODE_REROUTE))); + + if (g_batch_link.batch == NULL) { + nodelink_batch_init(); } - 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]); + + if (g_batch_link.enabled) { + /* Add link to batch. */ + nodelink_batch_add_link(snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow); + } + else { + /* Draw single link. */ + float colors[3][4] = {{0.0f}}; + if (th_col3 != -1) { + UI_GetThemeColor4fv(th_col3, colors[0]); + } + UI_GetThemeColor4fv(th_col1, colors[1]); + UI_GetThemeColor4fv(th_col2, colors[2]); + + Gwn_Batch *batch = g_batch_link.batch_single; + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); + GWN_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec); + GWN_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors); + GWN_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH); + GWN_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); + GWN_batch_uniform_1i(batch, "doArrow", drawarrow); + GWN_batch_draw(batch); } - glEnd(); } - - 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) { - bool do_shaded = false; - bool do_triple = false; int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE; if (link->fromsock == NULL && link->tosock == NULL) @@ -3652,8 +3613,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) /* new connection */ if (!link->fromsock || !link->tosock) { - th_col1 = TH_ACTIVE; - do_triple = true; + th_col1 = th_col2 = TH_ACTIVE; } else { /* going to give issues once... */ @@ -3674,39 +3634,38 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) if (link->tonode && link->tonode->flag & SELECT) th_col2 = TH_EDGE_SELECT; } - do_shaded = true; - do_triple = true; } else { - th_col1 = TH_REDALERT; + th_col1 = th_col2 = TH_REDALERT; + // th_col3 = -1; /* no shadow */ } } - node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); + node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3); // 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_add.c b/source/blender/editors/space_node/node_add.c index 3ae909041c2..8f6a0f5c4e2 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -317,10 +317,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) switch (snode->nodetree->type) { case NTREE_SHADER: - if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C))) - type = SH_NODE_TEX_IMAGE; - else - type = SH_NODE_TEXTURE; + type = SH_NODE_TEX_IMAGE; break; case NTREE_TEXTURE: type = TEX_NODE_IMAGE; @@ -341,14 +338,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (type == SH_NODE_TEXTURE) { - Tex *tex = BKE_texture_add(CTX_data_main(C), DATA_(ima->id.name)); - tex->ima = ima; - node->id = (ID *)tex; - WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, node->id); - } - else - node->id = (ID *)ima; + node->id = (ID *)ima; /* When adding new image file via drag-drop we need to load imbuf in order * to get proper image source. diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 6104761eb49..c2efc548c30 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -224,7 +224,7 @@ static bool node_properties_poll(bContext *C) void NODE_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "NODE_OT_properties"; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 3b6a227d124..01e22ec5245 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -44,16 +44,23 @@ #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 "GPU_state.h" +#include "GPU_framebuffer.h" + #include "WM_api.h" #include "WM_types.h" @@ -128,10 +135,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 +151,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); } } @@ -615,113 +622,24 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) { bNodeLink *link; - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); + GPU_blend(true); for (link = node->internal_links.first; link; link = link->next) - node_draw_link_bezier(v2d, snode, link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE); + node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1); - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); + GPU_blend(false); } -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) +static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col) { - 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) -{ - 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 *********** */ @@ -730,10 +648,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) { @@ -744,7 +667,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) { @@ -756,9 +679,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 */ @@ -788,18 +712,20 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */ + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_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); + GPU_blend(false); - 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_box_wire_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 */ @@ -824,32 +750,139 @@ 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); + + GPU_blend(true); + 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(); + GPU_blend(false); } 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; - /* XXX hack: copy values from linked ID data where displayed as sockets */ - if (node->block) - 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; @@ -858,23 +891,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); + GPU_line_width(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; @@ -907,10 +941,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? */ { @@ -925,17 +961,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) @@ -948,54 +976,29 @@ 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) { @@ -1016,56 +1019,53 @@ 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_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color); + else + UI_GetThemeColor4fv(color_id, color); - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); + 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); + UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); - 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_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); } /* custom color inline */ if (node->flag & NODE_CUSTOM_COLOR) { - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); + GPU_blend(true); + GPU_line_smooth(true); - 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); + GPU_line_smooth(false); + GPU_blend(false); } /* 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 */ { @@ -1080,18 +1080,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)); @@ -1105,28 +1100,34 @@ 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); - } - } + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, rct->xmax - dx, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - for (sock = node->outputs.first; sock; sock = sock->next) { - if (!nodeSocketIsHidden(sock)) { - node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT); - } - } + 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); @@ -1240,14 +1241,14 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT } /* node lines */ - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); + GPU_blend(true); + nodelink_batch_start(snode); for (link = ntree->links.first; link; link = link->next) { if (!nodeLinkIsHidden(link)) node_draw_link(&ar->v2d, snode, link); } - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + nodelink_batch_end(snode); + GPU_blend(false); /* draw foreground nodes, last nodes in front */ for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) { @@ -1268,7 +1269,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)); } @@ -1301,13 +1302,15 @@ 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); + GPU_blend(true); + + 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); - glDisable(GL_BLEND); + UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); + GPU_blend(false); /* set the block bounds to clip mouse events from underlying nodes */ block = UI_block_begin(C, ar, "node tree bounds block", UI_EMBOSS); @@ -1324,7 +1327,7 @@ void drawnodespace(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; UI_ThemeClearColor(TH_BACK); - glClear(GL_COLOR_BUFFER_BIT); + GPU_clear(GPU_COLOR_BIT); UI_view2d_view_ortho(v2d); @@ -1337,8 +1340,7 @@ void drawnodespace(const bContext *C, ARegion *ar) ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); /* only set once */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_MAP1_VERTEX_3); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); /* nodes */ snode_set_context(C); @@ -1399,18 +1401,33 @@ 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(); + + 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); } /* temporary links */ - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); + GPU_blend(true); + GPU_line_smooth(true); for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) node_draw_link(v2d, snode, (bNodeLink *)linkdata->data); } - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + GPU_line_smooth(false); + GPU_blend(false); if (snode->flag & SNODE_SHOW_GPENCIL) { /* draw grease-pencil ('canvas' strokes) */ diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index c49c8c201c4..cc32e5ef499 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" @@ -124,7 +125,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) { @@ -331,11 +332,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) @@ -385,7 +386,6 @@ bool ED_node_is_texture(struct SpaceNode *snode) /* called from shading buttons or header */ void ED_node_shader_default(const bContext *C, ID *id) { - Scene *scene = CTX_data_scene(C); bNode *in, *out; bNodeSocket *fromsock, *tosock, *sock; bNodeTree *ntree; @@ -400,14 +400,8 @@ 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)) { - output_type = SH_NODE_OUTPUT_MATERIAL; - shader_type = SH_NODE_BSDF_DIFFUSE; - } - else { - output_type = SH_NODE_OUTPUT; - shader_type = SH_NODE_MATERIAL; - } + output_type = SH_NODE_OUTPUT_MATERIAL; + shader_type = SH_NODE_BSDF_PRINCIPLED; copy_v3_v3(color, &ma->r); strength = 0.0f; @@ -458,18 +452,16 @@ void ED_node_shader_default(const bContext *C, ID *id) nodeAddLink(ntree, in, fromsock, out, tosock); /* default values */ - if (BKE_scene_use_new_shading_nodes(scene)) { - PointerRNA sockptr; - sock = in->inputs.first; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); + PointerRNA sockptr; + sock = in->inputs.first; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); - RNA_float_set_array(&sockptr, "default_value", color); + RNA_float_set_array(&sockptr, "default_value", color); - if (strength != 0.0f) { - sock = in->inputs.last; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); - RNA_float_set(&sockptr, "default_value", strength); - } + if (strength != 0.0f) { + sock = in->inputs.last; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr); + RNA_float_set(&sockptr, "default_value", strength); } ntreeUpdateTree(CTX_data_main(C), ntree); @@ -548,12 +540,6 @@ void snode_set_context(const bContext *C) bNodeTree *ntree = snode->nodetree; ID *id = snode->id, *from = snode->from; - /* we use this to signal warnings, when node shaders are drawn in wrong render engine */ - if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C))) - snode->flag |= SNODE_NEW_SHADERS; - else - snode->flag &= ~SNODE_NEW_SHADERS; - /* check the tree type */ if (!treetype || (treetype->poll && !treetype->poll(C, treetype))) @@ -641,7 +627,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO)) nodeClearActiveID(ntree, ID_TE); - if (ELEM(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL, + if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP, SH_NODE_OUTPUT_LINESTYLE)) { bNode *tnode; @@ -670,6 +656,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) GPU_material_free(&wo->gpumaterial); + ED_node_tag_update_nodetree(bmain, ntree, node); WM_main_add_notifier(NC_IMAGE, NULL); } @@ -692,22 +679,6 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) /* addnode() doesnt link this yet... */ node->id = (ID *)BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); } - else if (node->type == CMP_NODE_R_LAYERS) { - Scene *scene; - - for (scene = bmain->scene.first; scene; scene = scene->id.next) { - if (scene->nodetree && scene->use_nodes && ntreeHasTree(scene->nodetree, ntree)) { - if (node->id == NULL || node->id == (ID *)scene) { - int num_layers = BLI_listbase_count(&scene->r.layers); - scene->r.actlay = node->custom1; - /* Clamp the value, because it might have come from a different - * scene which could have more render layers than new one. - */ - scene->r.actlay = min_ff(scene->r.actlay, num_layers - 1); - } - } - } - } else if (node->type == CMP_NODE_COMPOSITE) { if (was_output == 0) { bNode *tnode; @@ -1277,7 +1248,7 @@ bool ED_node_select_check(ListBase *lb) /* goes over all scenes, reads render layers */ -static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); @@ -1307,48 +1278,14 @@ static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void NODE_OT_read_renderlayers(wmOperatorType *ot) +void NODE_OT_read_viewlayers(wmOperatorType *ot) { - ot->name = "Read Render Layers"; - ot->idname = "NODE_OT_read_renderlayers"; + ot->name = "Read View Layers"; + ot->idname = "NODE_OT_read_viewlayers"; ot->description = "Read all render layers of all used scenes"; - ot->exec = node_read_renderlayers_exec; - - ot->poll = composite_node_active; - - /* flags */ - ot->flag = 0; -} - -static int node_read_fullsamplelayers_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Main *bmain = CTX_data_main(C); - SpaceNode *snode = CTX_wm_space_node(C); - Scene *curscene = CTX_data_scene(C); - Render *re = RE_NewSceneRender(curscene); - - WM_cursor_wait(1); - RE_MergeFullSample(re, bmain, curscene, snode->nodetree); - WM_cursor_wait(0); - - /* note we are careful to send the right notifier, as otherwise the - * compositor would reexecute and overwrite the full sample result */ - WM_event_add_notifier(C, NC_SCENE | ND_COMPO_RESULT, NULL); - - return OPERATOR_FINISHED; -} - - -void NODE_OT_read_fullsamplelayers(wmOperatorType *ot) -{ - - ot->name = "Read Full Sample Layers"; - ot->idname = "NODE_OT_read_fullsamplelayers"; - ot->description = "Read all render layers of current scene, in full sample"; - - ot->exec = node_read_fullsamplelayers_exec; + ot->exec = node_read_viewlayers_exec; ot->poll = composite_node_active; @@ -1367,13 +1304,13 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) } } if (node) { - SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1); + ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1); - if (srl) { + if (view_layer) { PointerRNA op_ptr; WM_operator_properties_create(&op_ptr, "RENDER_OT_render"); - RNA_string_set(&op_ptr, "layer", srl->name); + RNA_string_set(&op_ptr, "layer", view_layer->name); RNA_string_set(&op_ptr, "scene", sce->id.name + 2); /* to keep keypositions */ diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index fd62c52bd5a..d7a43bda461 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -68,13 +68,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); @@ -133,8 +131,11 @@ void NODE_OT_backimage_fit(struct wmOperatorType *ot); void NODE_OT_backimage_sample(struct wmOperatorType *ot); /* drawnode.c */ +void nodelink_batch_start(struct SpaceNode *snode); +void nodelink_batch_end(struct SpaceNode *snode); + void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link); -void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3); +void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, int th_col2, int th_col3); bool node_link_bezier_points(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, float coord_array[][2], int resol); // 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 ); void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, bNodeInstanceKey parent_key); @@ -200,7 +201,7 @@ void NODE_OT_options_toggle(struct wmOperatorType *ot); void NODE_OT_node_copy_color(struct wmOperatorType *ot); void NODE_OT_read_fullsamplelayers(struct wmOperatorType *ot); -void NODE_OT_read_renderlayers(struct wmOperatorType *ot); +void NODE_OT_read_viewlayers(struct wmOperatorType *ot); void NODE_OT_render_changed(struct wmOperatorType *ot); void NODE_OT_output_file_add_socket(struct wmOperatorType *ot); @@ -222,6 +223,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..851e3973288 --- /dev/null +++ b/source/blender/editors/space_node/node_manipulators.c @@ -0,0 +1,621 @@ +/* + * ***** 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 "BLI_utildefines.h" +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" +#include "BLI_rect.h" + +#include "BKE_context.h" +#include "BKE_image.h" +#include "BKE_main.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) +{ + Main *bmain = CTX_data_main(C); + 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(bmain, 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) +{ + Main *bmain = CTX_data_main(C); + struct NodeCropWidgetGroup *crop_group = mgroup->customdata; + wmManipulator *mpr = crop_group->border; + + void *lock; + Image *ima = BKE_image_verify_viewer(bmain, 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) +{ + Main *bmain = CTX_data_main(C); + struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; + wmManipulator *mpr = sbeam_group->manipulator; + + void *lock; + Image *ima = BKE_image_verify_viewer(bmain, 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) +{ + Main *bmain = CTX_data_main(C); + struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; + + void *lock; + Image *ima = BKE_image_verify_viewer(bmain, 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/node_ops.c b/source/blender/editors/space_node/node_ops.c index d7ded62a988..2e429155ff7 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -94,8 +94,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_insert_offset); - WM_operatortype_append(NODE_OT_read_renderlayers); - WM_operatortype_append(NODE_OT_read_fullsamplelayers); + WM_operatortype_append(NODE_OT_read_viewlayers); WM_operatortype_append(NODE_OT_render_changed); WM_operatortype_append(NODE_OT_backimage_move); @@ -275,6 +274,8 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_backimage_fit", HOMEKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "NODE_OT_backimage_sample", ACTIONMOUSE, KM_PRESS, KM_ALT, 0); + WM_keymap_add_menu(keymap, "NODE_MT_specials", WKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "replace", false); kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_SHIFT, 0); @@ -303,9 +304,12 @@ void node_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "tweak", false); +#ifdef USE_WM_KEYMAP_27X WM_keymap_add_item(keymap, "NODE_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_delete_reconnect", XKEY, KM_PRESS, KM_CTRL, 0); +#endif + WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NODE_OT_delete_reconnect", DELKEY, KM_PRESS, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "NODE_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); @@ -335,8 +339,7 @@ void node_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "exit", true); - WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NODE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index e4c59bc9508..c4cd59b65f4 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -532,7 +532,7 @@ static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag)) char header[UI_MAX_DRAW_STR]; BLI_strncpy(header, IFACE_("LMB: drag node link, RMB: cancel"), sizeof(header)); - ED_area_headerprint(CTX_wm_area(C), header); + ED_workspace_status_text(C, header); } static int node_count_links(bNodeTree *ntree, bNodeSocket *sock) @@ -729,7 +729,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_RELEASE) { node_link_exit(C, op, true); - ED_area_headerprint(CTX_wm_area(C), NULL); + ED_workspace_status_text(C, NULL); ED_region_tag_redraw(ar); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index ef9ead3407c..b884db1ced4 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -449,10 +449,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) int compatibility = 0; if (ntree->type == NTREE_SHADER) { - if (BKE_scene_use_new_shading_nodes(arg->scene)) - compatibility = NODE_NEW_SHADING; - else - compatibility = NODE_OLD_SHADING; + compatibility = NODE_NEW_SHADING; } /* generate array of node types sorted by UI name */ @@ -638,7 +635,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b if (node->typeinfo->draw_buttons) { if (node->type != NODE_GROUP) { - split = uiLayoutSplit(layout, 0.35f, false); + split = uiLayoutSplit(layout, 0.5f, false); col = uiLayoutColumn(split, false); col = uiLayoutColumn(split, false); @@ -681,10 +678,10 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, label[i] = ' '; } label[indent] = '\0'; - BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s:", IFACE_(input->name)); + BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name)); /* split in label and value */ - split = uiLayoutSplit(layout, 0.35f, false); + split = uiLayoutSplit(layout, 0.5f, false); row = uiLayoutRow(split, true); @@ -706,7 +703,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, uiItemL(row, label, ICON_NONE); bt = block->buttons.last; - bt->drawflag = UI_BUT_TEXT_LEFT; + bt->drawflag = UI_BUT_TEXT_RIGHT; if (dependency_loop) { row = uiLayoutRow(split, false); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 33f4847c90f..fa6fa02cdc5 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -49,13 +49,16 @@ #include "ED_node.h" #include "ED_render.h" #include "ED_screen.h" -#include "WM_api.h" -#include "WM_types.h" #include "UI_resources.h" #include "UI_view2d.h" #include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" #include "node_intern.h" /* own include */ @@ -290,7 +293,7 @@ ARegion *node_has_tools_region(ScrArea *sa) /* ******************** default callbacks for node space ***************** */ -static SpaceLink *node_new(const bContext *UNUSED(C)) +static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *ar; SpaceNode *snode; @@ -316,7 +319,7 @@ static SpaceLink *node_new(const bContext *UNUSED(C)) BLI_addtail(&snode->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_BOTTOM; + ar->alignment = RGN_ALIGN_TOP; /* buttons/list view */ ar = MEM_callocN(sizeof(ARegion), "buttons for node"); @@ -381,12 +384,13 @@ 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, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* 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 = snode->shaderfrom; /* preview renders */ switch (wmn->category) { @@ -599,7 +603,7 @@ static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void node_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } /* add handlers, stuff you only do once or on area/region changes */ @@ -615,7 +619,7 @@ static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar) static void node_toolbar_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) @@ -643,6 +647,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,17 +749,31 @@ 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_ANIMPLAY: + case ND_LAYER: ED_region_tag_redraw(ar); break; } @@ -757,10 +783,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; @@ -825,6 +861,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; @@ -896,6 +943,32 @@ static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID } } + +static int node_space_subtype_get(ScrArea *sa) +{ + SpaceNode *snode = sa->spacedata.first; + return rna_node_tree_idname_to_enum(snode->tree_idname); +} + +static void node_space_subtype_set(ScrArea *sa, int value) +{ + SpaceNode *snode = sa->spacedata.first; + ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value)); +} + +static void node_space_subtype_item_extend( + bContext *C, EnumPropertyItem **item, int *totitem) +{ + bool free; + const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); + for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) { + RNA_enum_item_add(item, totitem, item_iter); + } + if (free) { + MEM_freeN((void *)item_src); + } +} + /* only called once, from space/spacetypes.c */ void ED_spacetype_node(void) { @@ -915,7 +988,11 @@ 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; + st->space_subtype_item_extend = node_space_subtype_item_extend; + st->space_subtype_get = node_space_subtype_get; + st->space_subtype_set = node_space_subtype_set; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype node region"); |