Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-02-16 19:55:10 +0300
committerHans Goudey <h.goudey@me.com>2021-02-16 19:55:10 +0300
commit520d965c77f9109492013d33cff659cd6055ff11 (patch)
tree5fbf5e6e8ffc917d158f6a46634209442efc3182 /source/blender/editors/space_node/node_draw.c
parent8971018eb64a68119687c74db875fd45f89cbdf8 (diff)
Cleanup: Compile node_draw.c with C++
This will allow using C++ data structures to draw node error messages. This required removing a forward declared enum for grease pencil undo. Compiles with clang tidy.
Diffstat (limited to 'source/blender/editors/space_node/node_draw.c')
-rw-r--r--source/blender/editors/space_node/node_draw.c2036
1 files changed, 0 insertions, 2036 deletions
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
deleted file mode 100644
index c7be5f848f7..00000000000
--- a/source/blender/editors/space_node/node_draw.c
+++ /dev/null
@@ -1,2036 +0,0 @@
-/*
- * 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.
- *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spnode
- * \brief higher level node drawing for the node editor.
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_light_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_material_types.h"
-#include "DNA_node_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_world_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
-#include "BLT_translation.h"
-
-#include "BKE_context.h"
-#include "BKE_lib_id.h"
-#include "BKE_main.h"
-#include "BKE_node.h"
-
-#include "DEG_depsgraph.h"
-
-#include "BLF_api.h"
-
-#include "BIF_glutil.h"
-
-#include "GPU_framebuffer.h"
-#include "GPU_immediate.h"
-#include "GPU_immediate_util.h"
-#include "GPU_matrix.h"
-#include "GPU_state.h"
-#include "GPU_viewport.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_gpencil.h"
-#include "ED_node.h"
-#include "ED_space_api.h"
-
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-#include "RNA_access.h"
-
-#include "node_intern.h" /* own include */
-
-#ifdef WITH_COMPOSITOR
-# include "COM_compositor.h"
-#endif
-
-/* XXX interface.h */
-extern void ui_draw_dropshadow(
- const rctf *rct, float radius, float aspect, float alpha, int select);
-
-float ED_node_grid_size(void)
-{
- return U.widget_unit;
-}
-
-void ED_node_tree_update(const bContext *C)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- if (snode) {
- snode_set_context(C);
-
- id_us_ensure_real(&snode->nodetree->id);
- }
-}
-
-/* id is supposed to contain a node tree */
-static bNodeTree *node_tree_from_ID(ID *id)
-{
- if (id) {
- if (GS(id->name) == ID_NT) {
- return (bNodeTree *)id;
- }
- return ntreeFromID(id);
- }
-
- return NULL;
-}
-
-void ED_node_tag_update_id(ID *id)
-{
- bNodeTree *ntree = node_tree_from_ID(id);
- if (id == NULL || ntree == NULL) {
- return;
- }
-
- /* TODO(sergey): With the new dependency graph it
- * should be just enough to only tag ntree itself,
- * all the users of this tree will have update
- * flushed from the tree,
- */
- DEG_id_tag_update(&ntree->id, 0);
-
- if (ntree->type == NTREE_SHADER) {
- DEG_id_tag_update(id, 0);
-
- if (GS(id->name) == ID_MA) {
- WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
- }
- else if (GS(id->name) == ID_LA) {
- WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
- }
- else if (GS(id->name) == ID_WO) {
- WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
- }
- }
- else if (ntree->type == NTREE_COMPOSIT) {
- WM_main_add_notifier(NC_SCENE | ND_NODES, id);
- }
- else if (ntree->type == NTREE_TEXTURE) {
- DEG_id_tag_update(id, 0);
- WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
- }
- else if (ntree->type == NTREE_GEOMETRY) {
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, id);
- }
- else if (id == &ntree->id) {
- /* node groups */
- DEG_id_tag_update(id, 0);
- }
-}
-
-void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
-{
- if (!ntree) {
- return;
- }
-
- bool do_tag_update = true;
- if (node != NULL) {
- if (!node_connected_to_output(bmain, ntree, node)) {
- do_tag_update = false;
- }
- }
-
- /* look through all datablocks, to support groups */
- if (do_tag_update) {
- FOREACH_NODETREE_BEGIN (bmain, tntree, id) {
- /* check if nodetree uses the group */
- if (ntreeHasTree(tntree, ntree)) {
- ED_node_tag_update_id(id);
- }
- }
- FOREACH_NODETREE_END;
- }
-
- if (ntree->type == NTREE_TEXTURE) {
- ntreeTexCheckCyclics(ntree);
- }
-}
-
-static bool compare_nodes(const bNode *a, const bNode *b)
-{
- /* These tell if either the node or any of the parent nodes is selected.
- * A selected parent means an unselected node is also in foreground!
- */
- bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
- bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
-
- /* if one is an ancestor of the other */
- /* XXX there might be a better sorting algorithm for stable topological sort,
- * this is O(n^2) worst case */
- for (bNode *parent = a->parent; parent; parent = parent->parent) {
- /* if b is an ancestor, it is always behind a */
- if (parent == b) {
- return true;
- }
- /* any selected ancestor moves the node forward */
- if (parent->flag & NODE_ACTIVE) {
- a_active = 1;
- }
- if (parent->flag & NODE_SELECT) {
- a_select = 1;
- }
- }
- for (bNode *parent = b->parent; parent; parent = parent->parent) {
- /* if a is an ancestor, it is always behind b */
- if (parent == a) {
- return false;
- }
- /* any selected ancestor moves the node forward */
- if (parent->flag & NODE_ACTIVE) {
- b_active = 1;
- }
- if (parent->flag & NODE_SELECT) {
- b_select = 1;
- }
- }
-
- /* if one of the nodes is in the background and the other not */
- if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) {
- return false;
- }
- if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) {
- return true;
- }
-
- /* if one has a higher selection state (active > selected > nothing) */
- if (!b_active && a_active) {
- return true;
- }
- if (!b_select && (a_active || a_select)) {
- return true;
- }
-
- return false;
-}
-
-/* Sorts nodes by selection: unselected nodes first, then selected,
- * then the active node at the very end. Relative order is kept intact!
- */
-void ED_node_sort(bNodeTree *ntree)
-{
- /* merge sort is the algorithm of choice here */
- int totnodes = BLI_listbase_count(&ntree->nodes);
-
- int k = 1;
- while (k < totnodes) {
- bNode *first_a = ntree->nodes.first;
- bNode *first_b = first_a;
-
- do {
- /* setup first_b pointer */
- for (int b = 0; b < k && first_b; b++) {
- first_b = first_b->next;
- }
- /* all batches merged? */
- if (first_b == NULL) {
- break;
- }
-
- /* merge batches */
- bNode *node_a = first_a;
- bNode *node_b = first_b;
- int a = 0;
- int b = 0;
- while (a < k && b < k && node_b) {
- if (compare_nodes(node_a, node_b) == 0) {
- node_a = node_a->next;
- a++;
- }
- else {
- bNode *tmp = node_b;
- node_b = node_b->next;
- b++;
- BLI_remlink(&ntree->nodes, tmp);
- BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
- }
- }
-
- /* setup first pointers for next batch */
- first_b = node_b;
- for (; b < k; b++) {
- /* all nodes sorted? */
- if (first_b == NULL) {
- break;
- }
- first_b = first_b->next;
- }
- first_a = first_b;
- } while (first_b);
-
- k = k << 1;
- }
-}
-
-static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
-{
- if (event == B_NODE_EXEC) {
- SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->id) {
- ED_node_tag_update_id(snode->id);
- }
- }
-}
-
-static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
-{
- /* add node uiBlocks in drawing order - prevents events going to overlapping nodes */
-
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- /* ui block */
- char uiblockstr[32];
- BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
- node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
- UI_block_func_handle_set(node->block, do_node_internal_buttons, node);
-
- /* this cancels events for background nodes */
- UI_block_flag_enable(node->block, UI_BLOCK_CLIP_EVENTS);
- }
-}
-
-void node_to_view(const bNode *node, float x, float y, float *rx, float *ry)
-{
- nodeToView(node, x, y, rx, ry);
- *rx *= UI_DPI_FAC;
- *ry *= UI_DPI_FAC;
-}
-
-void node_to_updated_rect(const bNode *node, rctf *r_rect)
-{
- node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
- node_to_view(node,
- node->offsetx + node->width,
- node->offsety - node->height,
- &r_rect->xmax,
- &r_rect->ymin);
-}
-
-void node_from_view(const bNode *node, float x, float y, float *rx, float *ry)
-{
- x /= UI_DPI_FAC;
- y /= UI_DPI_FAC;
- nodeFromView(node, x, y, rx, ry);
-}
-
-/* based on settings in node, sets drawing rect info. each redraw! */
-static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
-{
- PointerRNA nodeptr;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
-
- /* get "global" coords */
- float locx, locy;
- node_to_view(node, 0.0f, 0.0f, &locx, &locy);
- float dy = locy;
-
- /* header */
- dy -= NODE_DY;
-
- /* little bit space in top */
- if (node->outputs.first) {
- dy -= NODE_DYS / 2;
- }
-
- /* output sockets */
- bool add_output_space = false;
-
- int buty;
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
- if (nodeSocketIsHidden(nsock)) {
- continue;
- }
-
- PointerRNA sockptr;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
-
- uiLayout *layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- NODE_WIDTH(node) - NODE_DY,
- NODE_DY,
- 0,
- UI_style_get_dpi());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- /* context pointers for current node and socket */
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
- uiLayoutSetContextPointer(layout, "socket", &sockptr);
-
- /* align output buttons to the right */
- uiLayout *row = uiLayoutRow(layout, true);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
- const char *socket_label = nodeSocketLabel(nsock);
- nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- /* ensure minimum socket height in case layout is empty */
- buty = min_ii(buty, dy - NODE_DY);
-
- nsock->locx = locx + NODE_WIDTH(node);
- /* place the socket circle in the middle of the layout */
- nsock->locy = 0.5f * (dy + buty);
-
- dy = buty;
- if (nsock->next) {
- dy -= NODE_SOCKDY;
- }
-
- add_output_space = true;
- }
-
- if (add_output_space) {
- dy -= NODE_DY / 4;
- }
-
- node->prvr.xmin = locx + NODE_DYS;
- node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
-
- /* preview rect? */
- if (node->flag & NODE_PREVIEW) {
- float aspect = 1.0f;
-
- if (node->preview_xsize && node->preview_ysize) {
- aspect = (float)node->preview_ysize / (float)node->preview_xsize;
- }
-
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
-
- if (aspect <= 1.0f) {
- node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
- }
- else {
- /* width correction of image */
- /* XXX huh? (ton) */
- float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
-
- node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
-
- node->prvr.xmin += 0.5f * dx;
- node->prvr.xmax -= 0.5f * dx;
- }
-
- dy = node->prvr.ymin - NODE_DYS / 2;
-
- /* make sure that maximums are bigger or equal to minimums */
- if (node->prvr.xmax < node->prvr.xmin) {
- SWAP(float, node->prvr.xmax, node->prvr.xmin);
- }
- if (node->prvr.ymax < node->prvr.ymin) {
- SWAP(float, node->prvr.ymax, node->prvr.ymin);
- }
- }
-
- /* buttons rect? */
- if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
- dy -= NODE_DYS / 2;
-
- /* set this for uifunc() that don't use layout engine yet */
- node->butr.xmin = 0;
- node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
- node->butr.ymin = 0;
- node->butr.ymax = 0;
-
- uiLayout *layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- node->butr.xmax,
- 0,
- 0,
- UI_style_get_dpi());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
-
- node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- dy = buty - NODE_DYS / 2;
- }
-
- /* input sockets */
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
- if (nodeSocketIsHidden(nsock)) {
- continue;
- }
-
- PointerRNA sockptr;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
-
- /* Add the half the height of a multi-input socket to cursor Y
- * to account for the increased height of the taller sockets. */
- float multi_input_socket_offset = 0.0f;
- if (nsock->flag & SOCK_MULTI_INPUT) {
- if (nsock->total_inputs > 2) {
- multi_input_socket_offset = (nsock->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP;
- }
- }
- dy -= multi_input_socket_offset * 0.5f;
-
- uiLayout *layout = UI_block_layout(node->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- locx + NODE_DYS,
- dy,
- NODE_WIDTH(node) - NODE_DY,
- NODE_DY,
- 0,
- UI_style_get_dpi());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- /* context pointers for current node and socket */
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
- uiLayoutSetContextPointer(layout, "socket", &sockptr);
-
- uiLayout *row = uiLayoutRow(layout, true);
-
- const char *socket_label = nodeSocketLabel(nsock);
- nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- /* ensure minimum socket height in case layout is empty */
- buty = min_ii(buty, dy - NODE_DY);
-
- nsock->locx = locx;
- /* place the socket circle in the middle of the layout */
- nsock->locy = 0.5f * (dy + buty);
-
- dy = buty - multi_input_socket_offset * 0.5;
- if (nsock->next) {
- dy -= NODE_SOCKDY;
- }
- }
-
- /* little bit space in end */
- if (node->inputs.first || (node->flag & (NODE_OPTIONS | NODE_PREVIEW)) == 0) {
- dy -= NODE_DYS / 2;
- }
-
- node->totr.xmin = locx;
- node->totr.xmax = locx + NODE_WIDTH(node);
- node->totr.ymax = locy;
- node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add a margin for sockets on each side.
- */
- UI_block_bounds_set_explicit(node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
-}
-
-/* based on settings in node, sets drawing rect info. each redraw! */
-static void node_update_hidden(bNode *node)
-{
- int totin = 0, totout = 0;
-
- /* get "global" coords */
- float locx, locy;
- node_to_view(node, 0.0f, 0.0f, &locx, &locy);
-
- /* calculate minimal radius */
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
- if (!nodeSocketIsHidden(nsock)) {
- totin++;
- }
- }
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
- if (!nodeSocketIsHidden(nsock)) {
- totout++;
- }
- }
-
- float hiddenrad = HIDDEN_RAD;
- float tot = MAX2(totin, totout);
- if (tot > 4) {
- hiddenrad += 5.0f * (float)(tot - 4);
- }
-
- node->totr.xmin = locx;
- node->totr.xmax = locx + max_ff(NODE_WIDTH(node), 2 * hiddenrad);
- node->totr.ymax = locy + (hiddenrad - 0.5f * NODE_DY);
- node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
-
- /* output sockets */
- float rad = (float)M_PI / (1.0f + (float)totout);
- float drad = rad;
-
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
- rad += drad;
- }
- }
-
- /* input sockets */
- rad = drad = -(float)M_PI / (1.0f + (float)totin);
-
- LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
- rad += drad;
- }
- }
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add a margin for sockets on each side.
- */
- UI_block_bounds_set_explicit(node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
-}
-
-void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
-{
- if (node->flag & NODE_HIDDEN) {
- node_update_hidden(node);
- }
- else {
- node_update_basis(C, ntree, node);
- }
-}
-
-int node_select_area_default(bNode *node, int x, int y)
-{
- return BLI_rctf_isect_pt(&node->totr, x, y);
-}
-
-int node_tweak_area_default(bNode *node, int x, int y)
-{
- return BLI_rctf_isect_pt(&node->totr, x, y);
-}
-
-int node_get_colorid(bNode *node)
-{
- switch (node->typeinfo->nclass) {
- case NODE_CLASS_INPUT:
- return TH_NODE_INPUT;
- case NODE_CLASS_OUTPUT:
- return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
- case NODE_CLASS_CONVERTOR:
- return TH_NODE_CONVERTOR;
- case NODE_CLASS_OP_COLOR:
- return TH_NODE_COLOR;
- case NODE_CLASS_OP_VECTOR:
- return TH_NODE_VECTOR;
- case NODE_CLASS_OP_FILTER:
- return TH_NODE_FILTER;
- case NODE_CLASS_GROUP:
- return TH_NODE_GROUP;
- case NODE_CLASS_INTERFACE:
- return TH_NODE_INTERFACE;
- case NODE_CLASS_MATTE:
- return TH_NODE_MATTE;
- case NODE_CLASS_DISTORT:
- return TH_NODE_DISTORT;
- case NODE_CLASS_TEXTURE:
- return TH_NODE_TEXTURE;
- case NODE_CLASS_SHADER:
- return TH_NODE_SHADER;
- case NODE_CLASS_SCRIPT:
- return TH_NODE_SCRIPT;
- case NODE_CLASS_PATTERN:
- return TH_NODE_PATTERN;
- case NODE_CLASS_LAYOUT:
- return TH_NODE_LAYOUT;
- case NODE_CLASS_GEOMETRY:
- return TH_NODE_GEOMETRY;
- case NODE_CLASS_ATTRIBUTE:
- return TH_NODE_ATTRIBUTE;
- default:
- return TH_NODE;
- }
-}
-
-/* note: in cmp_util.c is similar code, for node_compo_pass_on()
- * the same goes for shader and texture nodes. */
-/* note: in node_edit.c is similar code, for untangle node */
-static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node)
-{
- GPU_blend(GPU_BLEND_ALPHA);
-
- LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) {
- node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
- }
-
- GPU_blend(GPU_BLEND_NONE);
-}
-
-/* flags used in gpu_shader_keyframe_diamond_frag.glsl */
-#define MARKER_SHAPE_DIAMOND 0x1
-#define MARKER_SHAPE_SQUARE 0xC
-#define MARKER_SHAPE_CIRCLE 0x2
-#define MARKER_SHAPE_INNER_DOT 0x10
-
-static void node_socket_draw(const bNodeSocket *sock,
- const float color[4],
- const float color_outline[4],
- float size,
- int locx,
- int locy,
- uint pos_id,
- uint col_id,
- uint shape_id,
- uint size_id,
- uint outline_col_id)
-{
- int flags;
-
- /* sets shape flags */
- switch (sock->display_shape) {
- case SOCK_DISPLAY_SHAPE_DIAMOND:
- case SOCK_DISPLAY_SHAPE_DIAMOND_DOT:
- flags = MARKER_SHAPE_DIAMOND;
- break;
- case SOCK_DISPLAY_SHAPE_SQUARE:
- case SOCK_DISPLAY_SHAPE_SQUARE_DOT:
- flags = MARKER_SHAPE_SQUARE;
- break;
- default:
- case SOCK_DISPLAY_SHAPE_CIRCLE:
- case SOCK_DISPLAY_SHAPE_CIRCLE_DOT:
- flags = MARKER_SHAPE_CIRCLE;
- break;
- }
-
- if (ELEM(sock->display_shape,
- SOCK_DISPLAY_SHAPE_DIAMOND_DOT,
- SOCK_DISPLAY_SHAPE_SQUARE_DOT,
- SOCK_DISPLAY_SHAPE_CIRCLE_DOT)) {
- flags |= MARKER_SHAPE_INNER_DOT;
- }
-
- immAttr4fv(col_id, color);
- immAttr1u(shape_id, flags);
- immAttr1f(size_id, size);
- immAttr4fv(outline_col_id, color_outline);
- immVertex2f(pos_id, locx, locy);
-}
-
-static void node_socket_draw_multi_input(const float color[4],
- const float color_outline[4],
- const float width,
- const float height,
- const int locx,
- const int locy)
-{
- const float outline_width = 1.0f;
- /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */
- const rctf rect = {
- .xmin = locx - width + outline_width * 0.5f,
- .xmax = locx + width - outline_width * 0.5f,
- .ymin = locy - height + outline_width * 0.5f,
- .ymax = locy + height - outline_width * 0.5f,
- };
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv_ex(
- &rect, color, NULL, 1.0f, color_outline, outline_width, width - outline_width * 0.5f);
-}
-
-static void node_socket_outline_color_get(bool selected, float r_outline_color[4])
-{
- if (selected) {
- UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color);
- r_outline_color[3] = 0.9f;
- }
- else {
- copy_v4_fl(r_outline_color, 0.0f);
- r_outline_color[3] = 0.6f;
- }
-}
-
-/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a
- * color property socket). */
-void node_socket_color_get(
- bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
-{
- PointerRNA ptr;
- BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node));
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
-
- sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color);
-
- bNode *node = node_ptr->data;
- if (node->flag & NODE_MUTED) {
- r_color[3] *= 0.25f;
- }
-}
-
-static void node_socket_draw_nested(const bContext *C,
- bNodeTree *ntree,
- PointerRNA *node_ptr,
- bNodeSocket *sock,
- uint pos_id,
- uint col_id,
- uint shape_id,
- uint size_id,
- uint outline_col_id,
- float size,
- bool selected)
-{
- float color[4];
- float outline_color[4];
-
- node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color);
- node_socket_outline_color_get(selected, outline_color);
-
- node_socket_draw(sock,
- color,
- outline_color,
- size,
- sock->locx,
- sock->locy,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id);
-}
-
-/**
- * Draw a single node socket at default size.
- * \note this is only called from external code, internally #node_socket_draw_nested() is used for
- * optimized drawing of multiple/all sockets of a node.
- */
-void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
-{
- const float size = 2.25f * NODE_SOCKSIZE * scale;
- rcti draw_rect = *rect;
- float outline_color[4] = {0};
-
- node_socket_outline_color_get(sock->flag & SELECT, outline_color);
-
- BLI_rcti_resize(&draw_rect, size, size);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint outline_col_id = GPU_vertformat_attr_add(
- format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- eGPUBlend state = GPU_blend_get();
- GPU_blend(GPU_BLEND_ALPHA);
- GPU_program_point_size(true);
-
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- immUniform1f("outline_scale", 0.7f);
- immUniform2f("ViewportSize", -1.0f, -1.0f);
-
- /* Single point */
- immBegin(GPU_PRIM_POINTS, 1);
- node_socket_draw(sock,
- color,
- outline_color,
- BLI_rcti_size_y(&draw_rect),
- BLI_rcti_cent_x(&draw_rect),
- BLI_rcti_cent_y(&draw_rect),
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id);
- immEnd();
-
- immUnbindProgram();
- GPU_program_point_size(false);
-
- /* Restore. */
- GPU_blend(state);
-}
-
-/* ************** Socket callbacks *********** */
-
-static void node_draw_preview_background(rctf *rect)
-{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
-
- /* Drawing the checkerboard. */
- const float checker_dark = UI_ALPHA_CHECKER_DARK / 255.0f;
- const float checker_light = UI_ALPHA_CHECKER_LIGHT / 255.0f;
- immUniform4f("color1", checker_dark, checker_dark, checker_dark, 1.0f);
- immUniform4f("color2", checker_light, checker_light, checker_light, 1.0f);
- immUniform1i("size", 8);
- immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- immUnbindProgram();
-}
-
-/* not a callback */
-static void node_draw_preview(bNodePreview *preview, rctf *prv)
-{
- float xrect = BLI_rctf_size_x(prv);
- float yrect = BLI_rctf_size_y(prv);
- float xscale = xrect / ((float)preview->xsize);
- float yscale = yrect / ((float)preview->ysize);
- float scale;
-
- /* uniform scale and offset */
- rctf draw_rect = *prv;
- if (xscale < yscale) {
- float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
- draw_rect.ymin += offset;
- draw_rect.ymax -= offset;
- scale = xscale;
- }
- else {
- float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
- draw_rect.xmin += offset;
- draw_rect.xmax -= offset;
- scale = yscale;
- }
-
- node_draw_preview_background(&draw_rect);
-
- GPU_blend(GPU_BLEND_ALPHA);
- /* premul graphics */
- GPU_blend(GPU_BLEND_ALPHA);
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state,
- draw_rect.xmin,
- draw_rect.ymin,
- preview->xsize,
- preview->ysize,
- GPU_RGBA8,
- true,
- preview->rect,
- scale,
- scale,
- NULL);
-
- GPU_blend(GPU_BLEND_NONE);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_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 */
-static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
-{
- bNode *node = (bNode *)node_argv;
- const char *opname = (const char *)op_argv;
-
- /* select & activate only the button's node */
- node_select_single(C, node);
-
- WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
-}
-
-void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha)
-{
- const rctf *rct = &node->totr;
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- ui_draw_dropshadow(rct, radius, snode->runtime->aspect, alpha, node->flag & SELECT);
-}
-
-void node_draw_sockets(const View2D *v2d,
- const bContext *C,
- bNodeTree *ntree,
- bNode *node,
- bool draw_outputs,
- bool select_all)
-{
- const uint total_input_len = BLI_listbase_count(&node->inputs);
- const uint total_output_len = BLI_listbase_count(&node->outputs);
-
- if (total_input_len + total_output_len == 0) {
- return;
- }
-
- PointerRNA node_ptr;
- RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
-
- bool selected = false;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint outline_col_id = GPU_vertformat_attr_add(
- format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- GPU_blend(GPU_BLEND_ALPHA);
- GPU_program_point_size(true);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- immUniform1f("outline_scale", 0.7f);
- immUniform2f("ViewportSize", -1.0f, -1.0f);
-
- /* set handle size */
- float scale;
- UI_view2d_scale_get(v2d, &scale, NULL);
- scale *= 2.25f * NODE_SOCKSIZE;
-
- if (!select_all) {
- immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
- }
-
- /* socket inputs */
- short selected_input_len = 0;
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- selected_input_len++;
- continue;
- }
- /* Don't draw multi-input sockets here since they are drawn in a different batch. */
- if (sock->flag & SOCK_MULTI_INPUT) {
- continue;
- }
-
- node_socket_draw_nested(C,
- ntree,
- &node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
- }
-
- /* socket outputs */
- short selected_output_len = 0;
- if (draw_outputs) {
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- selected_output_len++;
- continue;
- }
-
- node_socket_draw_nested(C,
- ntree,
- &node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
- }
- }
-
- if (!select_all) {
- immEnd();
- }
-
- /* go back and draw selected sockets */
- if (selected_input_len + selected_output_len > 0) {
- /* outline for selected sockets */
-
- selected = true;
-
- immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
-
- if (selected_input_len) {
- /* socket inputs */
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- node_socket_draw_nested(C,
- ntree,
- &node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
- if (--selected_input_len == 0) {
- break; /* stop as soon as last one is drawn */
- }
- }
- }
- }
-
- if (selected_output_len) {
- /* socket outputs */
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- node_socket_draw_nested(C,
- ntree,
- &node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
- if (--selected_output_len == 0) {
- break; /* stop as soon as last one is drawn */
- }
- }
- }
- }
-
- immEnd();
- }
-
- immUnbindProgram();
-
- GPU_program_point_size(false);
- GPU_blend(GPU_BLEND_NONE);
-
- /* Draw multi-input sockets after the others because they are drawn with `UI_draw_roundbox`
- * rather than with `GL_POINT`. */
- LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
- if (nodeSocketIsHidden(socket)) {
- continue;
- }
- if (!(socket->flag & SOCK_MULTI_INPUT)) {
- continue;
- }
-
- const bool is_node_hidden = (node->flag & NODE_HIDDEN);
- const float width = NODE_SOCKSIZE;
- float height = is_node_hidden ? width : node_socket_calculate_height(socket) - width;
-
- float color[4];
- float outline_color[4];
- node_socket_color_get((bContext *)C, ntree, &node_ptr, socket, color);
- node_socket_outline_color_get(selected, outline_color);
-
- node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy);
- }
-}
-
-static void node_draw_basis(const bContext *C,
- const View2D *v2d,
- const SpaceNode *snode,
- bNodeTree *ntree,
- bNode *node,
- bNodeInstanceKey key)
-{
- /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
- float iconbutw = 0.8f * UI_UNIT_X;
-
- /* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
- UI_block_end(C, node->block);
- node->block = NULL;
- return;
- }
-
- /* shadow */
- node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
-
- float color[4];
- int color_id = node_get_colorid(node);
- if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor3fv(TH_NODE, color);
- color[3] = 0.25f;
- }
- else {
- /* Opaque headers for regular nodes. */
- UI_GetThemeColor3fv(color_id, color);
- color[3] = 1.0f;
- }
-
- GPU_line_width(1.0f);
-
- rctf *rct = &node->totr;
- UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_draw_roundbox_aa(
- &(const rctf){
- .xmin = rct->xmin,
- .xmax = rct->xmax,
- .ymin = rct->ymax - NODE_DY,
- .ymax = rct->ymax,
- },
- true,
- BASIS_RAD,
- color);
-
- /* show/hide icons */
- float iconofs = rct->xmax - 0.35f * U.widget_unit;
-
- /* preview */
- if (node->typeinfo->flag & NODE_PREVIEW) {
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- uiBut *but = uiDefIconBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- B_REDR,
- ICON_MATERIAL,
- iconofs,
- rct->ymax - NODE_DY,
- iconbutw,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
- /* XXX this does not work when node is activated and the operator called right afterwards,
- * since active ID is not updated yet (needs to process the notifier).
- * This can only work as visual indicator!
- */
- // if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
- // UI_but_flag_enable(but, UI_BUT_DISABLED);
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
- /* group edit */
- if (node->type == NODE_GROUP) {
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- uiBut *but = uiDefIconBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- B_REDR,
- ICON_NODETREE,
- iconofs,
- rct->ymax - NODE_DY,
- iconbutw,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
- if (node->type == NODE_CUSTOM && node->typeinfo->ui_icon != ICON_NONE) {
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- uiDefIconBut(node->block,
- UI_BTYPE_BUT,
- 0,
- node->typeinfo->ui_icon,
- iconofs,
- rct->ymax - NODE_DY,
- iconbutw,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
-
- /* title */
- if (node->flag & SELECT) {
- UI_GetThemeColor4fv(TH_SELECT, color);
- }
- else {
- UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
- }
-
- /* open/close entirely? */
- {
- int but_size = U.widget_unit * 0.8f;
- /* XXX button uses a custom triangle draw below, so make it invisible without icon */
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- uiBut *but = uiDefBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- B_REDR,
- "",
- rct->xmin + 0.35f * U.widget_unit,
- rct->ymax - NODE_DY / 2.2f - but_size / 2,
- but_size,
- but_size,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
-
- UI_GetThemeColor4fv(TH_TEXT, color);
- /* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
- }
-
- char showname[128]; /* 128 used below */
- nodeLabel(ntree, node, showname, sizeof(showname));
-
- uiBut *but = uiDefBut(node->block,
- UI_BTYPE_LABEL,
- 0,
- showname,
- (int)(rct->xmin + NODE_MARGIN_X),
- (int)(rct->ymax - NODE_DY),
- (short)(iconofs - rct->xmin - (18.0f * U.dpi_fac)),
- (short)NODE_DY,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- if (node->flag & NODE_MUTED) {
- UI_but_flag_enable(but, UI_BUT_INACTIVE);
- }
-
- /* body */
- if (nodeTypeUndefined(node)) {
- /* use warning color to indicate undefined types */
- UI_GetThemeColor4fv(TH_REDALERT, color);
- }
- else if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor4fv(TH_NODE, color);
- }
- 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_GetThemeColor4fv(TH_NODE, color);
- }
-
- if (node->flag & NODE_MUTED) {
- color[3] = 0.5f;
- }
-
- UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
- UI_draw_roundbox_aa(
- &(const rctf){
- .xmin = rct->xmin,
- .xmax = rct->xmax,
- .ymin = rct->ymin,
- .ymax = rct->ymax - NODE_DY,
- },
- true,
- BASIS_RAD,
- color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- UI_GetThemeColorShadeAlpha4fv(
- (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(
- &(const rctf){
- .xmin = rct->xmin,
- .xmax = rct->xmax,
- .ymin = rct->ymin,
- .ymax = rct->ymax,
- },
- false,
- BASIS_RAD,
- color);
- }
-
- /* disable lines */
- if (node->flag & NODE_MUTED) {
- node_draw_mute_line(v2d, snode, node);
- }
-
- node_draw_sockets(v2d, C, ntree, node, true, false);
-
- /* preview */
- bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
- if (node->flag & NODE_PREVIEW && previews) {
- bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
- if (preview && (preview->xsize && preview->ysize)) {
- if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
- node_draw_preview(preview, &node->prvr);
- }
- }
- }
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
-}
-
-static void node_draw_hidden(const bContext *C,
- const View2D *v2d,
- const SpaceNode *snode,
- bNodeTree *ntree,
- bNode *node,
- bNodeInstanceKey UNUSED(key))
-{
- rctf *rct = &node->totr;
- float centy = BLI_rctf_cent_y(rct);
- float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
-
- float scale;
- UI_view2d_scale_get(v2d, &scale, NULL);
-
- /* shadow */
- node_draw_shadow(snode, node, hiddenrad, 1.0f);
-
- /* body */
- float color[4];
- int color_id = node_get_colorid(node);
- if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor4fv(TH_NODE, color);
- color[3] = 0.25f;
- }
- else {
- UI_GetThemeColor4fv(color_id, color);
- }
-
- UI_draw_roundbox_aa(rct, true, hiddenrad, color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- UI_GetThemeColorShadeAlpha4fv(
- (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
-
- UI_draw_roundbox_aa(rct, false, hiddenrad, color);
- }
-
- /* custom color inline */
- if (node->flag & NODE_CUSTOM_COLOR) {
- GPU_blend(GPU_BLEND_ALPHA);
- GPU_line_smooth(true);
-
- UI_draw_roundbox_3fv_alpha(
- &(const rctf){
- .xmin = rct->xmin + 1,
- .xmax = rct->xmax - 1,
- .ymin = rct->ymin + 1,
- .ymax = rct->ymax - 1,
- },
- false,
- hiddenrad,
- node->color,
- 1.0f);
-
- GPU_line_smooth(false);
- GPU_blend(GPU_BLEND_NONE);
- }
-
- /* title */
- if (node->flag & SELECT) {
- UI_GetThemeColor4fv(TH_SELECT, color);
- }
- else {
- UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
- }
-
- /* open entirely icon */
- {
- int but_size = U.widget_unit * 0.8f;
- /* XXX button uses a custom triangle draw below, so make it invisible without icon */
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- uiBut *but = uiDefBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- B_REDR,
- "",
- rct->xmin + 0.35f * U.widget_unit,
- centy - but_size / 2,
- but_size,
- but_size,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
-
- UI_GetThemeColor4fv(TH_TEXT, color);
- /* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, centy, 'h', color);
- }
-
- /* disable lines */
- if (node->flag & NODE_MUTED) {
- node_draw_mute_line(v2d, snode, node);
- }
-
- char showname[128]; /* 128 is used below */
- nodeLabel(ntree, node, showname, sizeof(showname));
-
- /* XXX - don't print into self! */
- // if (node->flag & NODE_MUTED)
- // BLI_snprintf(showname, sizeof(showname), "[%s]", showname);
-
- uiBut *but = uiDefBut(node->block,
- UI_BTYPE_LABEL,
- 0,
- showname,
- round_fl_to_int(rct->xmin + NODE_MARGIN_X),
- round_fl_to_int(centy - NODE_DY * 0.5f),
- (short)(BLI_rctf_size_x(rct) - ((18.0f + 12.0f) * U.dpi_fac)),
- (short)NODE_DY,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- if (node->flag & NODE_MUTED) {
- UI_but_flag_enable(but, UI_BUT_INACTIVE);
- }
-
- /* scale widget thing */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformThemeColorShade(color_id, -10);
- float dx = 10.0f;
-
- immBegin(GPU_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->runtime->aspect, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f);
- immEnd();
-
- immUniformThemeColorShade(color_id, 30);
- dx -= snode->runtime->aspect;
-
- immBegin(GPU_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->runtime->aspect, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f);
- immEnd();
-
- immUnbindProgram();
-
- node_draw_sockets(v2d, C, ntree, node, true, false);
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
-}
-
-int node_get_resize_cursor(int directions)
-{
- if (directions == 0) {
- return WM_CURSOR_DEFAULT;
- }
- if ((directions & ~(NODE_RESIZE_TOP | NODE_RESIZE_BOTTOM)) == 0) {
- return WM_CURSOR_Y_MOVE;
- }
- if ((directions & ~(NODE_RESIZE_RIGHT | NODE_RESIZE_LEFT)) == 0) {
- return WM_CURSOR_X_MOVE;
- }
- return WM_CURSOR_EDIT;
-}
-
-void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
-{
- bNodeTree *ntree = snode->edittree;
- bNode *node;
- bNodeSocket *sock;
- int wmcursor = WM_CURSOR_DEFAULT;
-
- if (ntree) {
- if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
- /* pass */
- }
- else {
- /* check nodes front to back */
- for (node = ntree->nodes.last; node; node = node->prev) {
- if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1])) {
- break; /* first hit on node stops */
- }
- }
- if (node) {
- int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
- wmcursor = node_get_resize_cursor(dir);
- }
- }
- }
-
- WM_cursor_set(win, wmcursor);
-}
-
-void node_draw_default(const bContext *C,
- ARegion *region,
- SpaceNode *snode,
- bNodeTree *ntree,
- bNode *node,
- bNodeInstanceKey key)
-{
- const View2D *v2d = &region->v2d;
- if (node->flag & NODE_HIDDEN) {
- node_draw_hidden(C, v2d, snode, ntree, node, key);
- }
- else {
- node_draw_basis(C, v2d, snode, ntree, node, key);
- }
-}
-
-static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
-{
- if (node->typeinfo->draw_nodetype_prepare) {
- node->typeinfo->draw_nodetype_prepare(C, ntree, node);
- }
-}
-
-static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
-{
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- LISTBASE_FOREACH (struct bNodeSocket *, socket, &node->inputs) {
- if (socket->flag & SOCK_MULTI_INPUT) {
- socket->total_inputs = 0;
- LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
- if (link->tosock == socket) {
- socket->total_inputs++;
- }
- }
- /* Count temporary links going into this socket. */
- LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
- if (link->tosock == socket) {
- socket->total_inputs++;
- }
- }
- }
- }
- }
- }
-}
-
-void node_update_nodetree(const bContext *C, bNodeTree *ntree)
-{
- /* make sure socket "used" tags are correct, for displaying value buttons */
- SpaceNode *snode = CTX_wm_space_node(C);
- ntreeTagUsedSockets(ntree);
-
- count_mutli_input_socket_links(ntree, snode);
-
- /* update nodes front to back, so children sizes get updated before parents */
- LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) {
- node_update(C, ntree, node);
- }
-}
-
-static int compare_link_by_angle_to_node(const void *a, const void *b)
-{
- const bNodeLink *link_a = *(const bNodeLink **)a;
- const bNodeLink *link_b = *(const bNodeLink **)b;
-
- BLI_assert(link_a->tosock == link_b->tosock);
- const float socket_location[2] = {link_a->tosock->locx, link_a->tosock->locy};
- const float up_direction[2] = {0.0f, 1.0f};
-
- float delta_a[2] = {link_a->fromsock->locx - socket_location[0],
- link_a->fromsock->locy - socket_location[1]};
- normalize_v2(delta_a);
- const float angle_a = angle_normalized_v2v2(up_direction, delta_a);
-
- float delta_b[2] = {link_b->fromsock->locx - socket_location[0],
- link_b->fromsock->locy - socket_location[1]};
- normalize_v2(delta_b);
- const float angle_b = angle_normalized_v2v2(up_direction, delta_b);
-
- return angle_a < angle_b ? 1 : -1;
-}
-
-static void node_draw(const bContext *C,
- ARegion *region,
- SpaceNode *snode,
- bNodeTree *ntree,
- bNode *node,
- bNodeInstanceKey key)
-{
- if (node->typeinfo->draw_nodetype) {
- node->typeinfo->draw_nodetype(C, region, snode, ntree, node, key);
- }
-}
-
-#define USE_DRAW_TOT_UPDATE
-
-/**
- * Automatically sort the input links to multi-input sockets to avoid crossing noodles.
- */
-static void sort_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
-{
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
- if (socket->flag & SOCK_MULTI_INPUT) {
- /* The total is calculated in #node_update_nodetree, which runs before this draw step. */
- const int total_inputs = socket->total_inputs;
- bNodeLink **input_links = MEM_malloc_arrayN(total_inputs, sizeof(bNodeLink *), __func__);
-
- int index = 0;
- LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
- if (link->tosock == socket) {
- input_links[index] = (bNodeLink *)link;
- index++;
- }
- }
- LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
- if (link->tosock == socket) {
- input_links[index] = (bNodeLink *)link;
- index++;
- }
- }
- }
-
- qsort(input_links, total_inputs, sizeof(bNodeLink *), compare_link_by_angle_to_node);
- for (int i = 0; i < total_inputs; i++) {
- input_links[i]->multi_input_socket_index = i;
- }
-
- MEM_freeN(input_links);
- }
- }
- }
-}
-
-void node_draw_nodetree(const bContext *C,
- ARegion *region,
- SpaceNode *snode,
- bNodeTree *ntree,
- bNodeInstanceKey parent_key)
-{
- if (ntree == NULL) {
- return; /* groups... */
- }
-
-#ifdef USE_DRAW_TOT_UPDATE
- if (ntree->nodes.first) {
- BLI_rctf_init_minmax(&region->v2d.tot);
- }
-#endif
-
- /* draw background nodes, last nodes in front */
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
-#ifdef USE_DRAW_TOT_UPDATE
- /* unrelated to background nodes, update the v2d->tot,
- * can be anywhere before we draw the scroll bars */
- BLI_rctf_union(&region->v2d.tot, &node->totr);
-#endif
-
- if (!(node->flag & NODE_BACKGROUND)) {
- continue;
- }
-
- bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
- node_draw(C, region, snode, ntree, node, key);
- }
-
- /* node lines */
- GPU_blend(GPU_BLEND_ALPHA);
- nodelink_batch_start(snode);
-
- sort_multi_input_socket_links(ntree, snode);
-
- LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
- if (!nodeLinkIsHidden(link)) {
- node_draw_link(&region->v2d, snode, link);
- }
- }
- nodelink_batch_end(snode);
- GPU_blend(GPU_BLEND_NONE);
-
- /* draw foreground nodes, last nodes in front */
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if (node->flag & NODE_BACKGROUND) {
- continue;
- }
-
- bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
- node_draw(C, region, snode, ntree, node, key);
- }
-}
-
-/* draw tree path info in lower left corner */
-static void draw_tree_path(SpaceNode *snode)
-{
- char info[256];
-
- ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
-
- 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));
-}
-
-static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float center[2])
-{
- View2D *v2d = &region->v2d;
-
- /* shift view to node tree center */
- UI_view2d_center_set(v2d, center[0], center[1]);
- UI_view2d_view_ortho(v2d);
-
- /* aspect+font, set each time */
- snode->runtime->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx;
- // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
-}
-
-static void draw_nodetree(const bContext *C,
- ARegion *region,
- bNodeTree *ntree,
- bNodeInstanceKey parent_key)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- node_uiblocks_init(C, ntree);
-
- node_update_nodetree(C, ntree);
- node_draw_nodetree(C, region, snode, ntree, parent_key);
-}
-
-/* shade the parent node group and add a uiBlock to clip mouse events */
-static void draw_group_overlay(const bContext *C, ARegion *region)
-{
- const View2D *v2d = &region->v2d;
- const rctf rect = v2d->cur;
- float color[4];
-
- /* shade node groups to separate them visually */
- GPU_blend(GPU_BLEND_ALPHA);
-
- UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color);
- UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_draw_roundbox_4fv(&rect, true, 0, color);
- GPU_blend(GPU_BLEND_NONE);
-
- /* set the block bounds to clip mouse events from underlying nodes */
- uiBlock *block = UI_block_begin(C, region, "node tree bounds block", UI_EMBOSS);
- UI_block_bounds_set_explicit(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS);
- UI_block_end(C, block);
-}
-
-void node_draw_space(const bContext *C, ARegion *region)
-{
- wmWindow *win = CTX_wm_window(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- View2D *v2d = &region->v2d;
-
- /* Setup offscreen buffers. */
- GPUViewport *viewport = WM_draw_region_get_viewport(region);
-
- GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
- GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
-
- UI_view2d_view_ortho(v2d);
- UI_ThemeClearColor(TH_BACK);
- GPU_depth_test(GPU_DEPTH_NONE);
- GPU_scissor_test(true);
-
- /* XXX snode->runtime->cursor set in coordspace for placing new nodes, used for drawing noodles
- * too */
- UI_view2d_region_to_view(&region->v2d,
- win->eventstate->x - region->winrct.xmin,
- win->eventstate->y - region->winrct.ymin,
- &snode->runtime->cursor[0],
- &snode->runtime->cursor[1]);
- snode->runtime->cursor[0] /= UI_DPI_FAC;
- snode->runtime->cursor[1] /= UI_DPI_FAC;
-
- int grid_levels = UI_GetThemeValueType(TH_NODE_GRID_LEVELS, SPACE_NODE);
-
- ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
-
- /* only set once */
- GPU_blend(GPU_BLEND_ALPHA);
-
- /* nodes */
- snode_set_context(C);
-
- /* draw parent node trees */
- if (snode->treepath.last) {
- static const int max_depth = 2;
-
- bNodeTreePath *path = snode->treepath.last;
-
- /* update tree path name (drawn in the bottom left) */
- ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id :
- snode->id;
-
- if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) {
- BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name));
- }
-
- /* current View2D center, will be set temporarily for parent node trees */
- float center[2];
- UI_view2d_center_get(v2d, &center[0], &center[1]);
-
- /* store new view center in path and current edittree */
- copy_v2_v2(path->view_center, center);
- if (snode->edittree) {
- copy_v2_v2(snode->edittree->view_center, center);
- }
-
- int depth = 0;
- while (path->prev && depth < max_depth) {
- path = path->prev;
- depth++;
- }
-
- /* parent node trees in the background */
- for (int curdepth = depth; curdepth > 0; path = path->next, curdepth--) {
- bNodeTree *ntree = path->nodetree;
- if (ntree) {
- snode_setup_v2d(snode, region, path->view_center);
-
- draw_nodetree(C, region, ntree, path->parent_key);
-
- draw_group_overlay(C, region);
- }
- }
-
- /* top-level edit tree */
- bNodeTree *ntree = path->nodetree;
- if (ntree) {
- snode_setup_v2d(snode, region, center);
-
- /* grid, uses theme color based on node path depth */
- UI_view2d_multi_grid_draw(v2d,
- (depth > 0 ? TH_NODE_GROUP : TH_GRID),
- ED_node_grid_size(),
- NODE_GRID_STEPS,
- grid_levels);
-
- /* backdrop */
- draw_nodespace_back_pix(C, region, snode, path->parent_key);
-
- {
- float original_proj[4][4];
- GPU_matrix_projection_get(original_proj);
-
- GPU_matrix_push();
- GPU_matrix_identity_set();
-
- wmOrtho2_pixelspace(region->winx, region->winy);
-
- WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
-
- GPU_matrix_pop();
- GPU_matrix_projection_set(original_proj);
- }
-
- draw_nodetree(C, region, ntree, path->parent_key);
- }
-
- /* temporary links */
- GPU_blend(GPU_BLEND_ALPHA);
- GPU_line_smooth(true);
- LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
- }
- }
- GPU_line_smooth(false);
- GPU_blend(GPU_BLEND_NONE);
-
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil ('canvas' strokes) */
- ED_annotation_draw_view2d(C, true);
- }
- }
- else {
- /* default grid */
- UI_view2d_multi_grid_draw(v2d, TH_GRID, ED_node_grid_size(), NODE_GRID_STEPS, grid_levels);
-
- /* backdrop */
- draw_nodespace_back_pix(C, region, snode, NODE_INSTANCE_KEY_NONE);
- }
-
- ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- if (snode->treepath.last) {
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* Draw grease-pencil (screen strokes, and also paint-buffer). */
- ED_annotation_draw_view2d(C, false);
- }
- }
-
- /* tree path info */
- draw_tree_path(snode);
-
- /* scrollers */
- UI_view2d_scrollers_draw(v2d, NULL);
-}