|
|
|
@ -175,7 +175,6 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
static bool compare_nodes(const bNode *a, const bNode *b)
|
|
|
|
|
{
|
|
|
|
|
bNode *parent;
|
|
|
|
|
/* 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!
|
|
|
|
|
*/
|
|
|
|
@ -185,7 +184,7 @@ static bool compare_nodes(const bNode *a, const bNode *b)
|
|
|
|
|
/* 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 (parent = a->parent; parent; parent = parent->parent) {
|
|
|
|
|
for (bNode *parent = a->parent; parent; parent = parent->parent) {
|
|
|
|
|
/* if b is an ancestor, it is always behind a */
|
|
|
|
|
if (parent == b) {
|
|
|
|
|
return true;
|
|
|
|
@ -198,7 +197,7 @@ static bool compare_nodes(const bNode *a, const bNode *b)
|
|
|
|
|
a_select = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (parent = b->parent; parent; parent = parent->parent) {
|
|
|
|
|
for (bNode *parent = b->parent; parent; parent = parent->parent) {
|
|
|
|
|
/* if a is an ancestor, it is always behind b */
|
|
|
|
|
if (parent == a) {
|
|
|
|
|
return false;
|
|
|
|
@ -237,17 +236,16 @@ static bool compare_nodes(const bNode *a, const bNode *b)
|
|
|
|
|
void ED_node_sort(bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
/* merge sort is the algorithm of choice here */
|
|
|
|
|
bNode *first_a, *first_b, *node_a, *node_b, *tmp;
|
|
|
|
|
int totnodes = BLI_listbase_count(&ntree->nodes);
|
|
|
|
|
int k, a, b;
|
|
|
|
|
|
|
|
|
|
k = 1;
|
|
|
|
|
int k = 1;
|
|
|
|
|
while (k < totnodes) {
|
|
|
|
|
first_a = first_b = ntree->nodes.first;
|
|
|
|
|
bNode *first_a = ntree->nodes.first;
|
|
|
|
|
bNode *first_b = first_a;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
/* setup first_b pointer */
|
|
|
|
|
for (b = 0; b < k && first_b; b++) {
|
|
|
|
|
for (int b = 0; b < k && first_b; b++) {
|
|
|
|
|
first_b = first_b->next;
|
|
|
|
|
}
|
|
|
|
|
/* all batches merged? */
|
|
|
|
@ -256,16 +254,17 @@ void ED_node_sort(bNodeTree *ntree)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* merge batches */
|
|
|
|
|
node_a = first_a;
|
|
|
|
|
node_b = first_b;
|
|
|
|
|
a = b = 0;
|
|
|
|
|
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 {
|
|
|
|
|
tmp = node_b;
|
|
|
|
|
bNode *tmp = node_b;
|
|
|
|
|
node_b = node_b->next;
|
|
|
|
|
b++;
|
|
|
|
|
BLI_remlink(&ntree->nodes, tmp);
|
|
|
|
@ -301,13 +300,12 @@ static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int even
|
|
|
|
|
|
|
|
|
|
static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
bNode *node;
|
|
|
|
|
char uiblockstr[32];
|
|
|
|
|
|
|
|
|
|
/* add node uiBlocks in drawing order - prevents events going to overlapping nodes */
|
|
|
|
|
|
|
|
|
|
for (node = ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
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);
|
|
|
|
@ -345,17 +343,14 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
|
|
|
|
|
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
uiLayout *layout, *row;
|
|
|
|
|
PointerRNA nodeptr, sockptr;
|
|
|
|
|
bNodeSocket *nsock;
|
|
|
|
|
float locx, locy;
|
|
|
|
|
float dy;
|
|
|
|
|
int buty;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
dy = locy;
|
|
|
|
|
float dy = locy;
|
|
|
|
|
|
|
|
|
|
/* header */
|
|
|
|
|
dy -= NODE_DY;
|
|
|
|
@ -368,11 +363,13 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
/* output sockets */
|
|
|
|
|
bool add_output_space = false;
|
|
|
|
|
|
|
|
|
|
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
int buty;
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
|
|
|
|
|
if (nodeSocketIsHidden(nsock)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PointerRNA sockptr;
|
|
|
|
|
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
|
|
|
|
|
|
|
|
|
|
layout = UI_block_layout(node->block,
|
|
|
|
@ -495,11 +492,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* input sockets */
|
|
|
|
|
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
|
|
|
|
|
if (nodeSocketIsHidden(nsock)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PointerRNA sockptr;
|
|
|
|
|
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
|
|
|
|
|
|
|
|
|
|
layout = UI_block_layout(node->block,
|
|
|
|
@ -564,27 +562,26 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
/* based on settings in node, sets drawing rect info. each redraw! */
|
|
|
|
|
static void node_update_hidden(bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *nsock;
|
|
|
|
|
float locx, locy;
|
|
|
|
|
float rad, drad, hiddenrad = HIDDEN_RAD;
|
|
|
|
|
int totin = 0, totout = 0, tot;
|
|
|
|
|
int totin = 0, totout = 0;
|
|
|
|
|
|
|
|
|
|
/* get "global" coords */
|
|
|
|
|
float locx, locy;
|
|
|
|
|
node_to_view(node, 0.0f, 0.0f, &locx, &locy);
|
|
|
|
|
|
|
|
|
|
/* calculate minimal radius */
|
|
|
|
|
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
|
|
|
|
|
if (!nodeSocketIsHidden(nsock)) {
|
|
|
|
|
totin++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
|
|
|
|
|
if (!nodeSocketIsHidden(nsock)) {
|
|
|
|
|
totout++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tot = MAX2(totin, totout);
|
|
|
|
|
float hiddenrad = HIDDEN_RAD;
|
|
|
|
|
float tot = MAX2(totin, totout);
|
|
|
|
|
if (tot > 4) {
|
|
|
|
|
hiddenrad += 5.0f * (float)(tot - 4);
|
|
|
|
|
}
|
|
|
|
@ -595,9 +592,10 @@ static void node_update_hidden(bNode *node)
|
|
|
|
|
node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
|
|
|
|
|
|
|
|
|
|
/* output sockets */
|
|
|
|
|
rad = drad = (float)M_PI / (1.0f + (float)totout);
|
|
|
|
|
float rad = (float)M_PI / (1.0f + (float)totout);
|
|
|
|
|
float drad = rad;
|
|
|
|
|
|
|
|
|
|
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
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;
|
|
|
|
@ -608,7 +606,7 @@ static void node_update_hidden(bNode *node)
|
|
|
|
|
/* input sockets */
|
|
|
|
|
rad = drad = -(float)M_PI / (1.0f + (float)totin);
|
|
|
|
|
|
|
|
|
|
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
|
|
|
|
|
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;
|
|
|
|
@ -689,11 +687,9 @@ int node_get_colorid(bNode *node)
|
|
|
|
|
/* note: in node_edit.c is similar code, for untangle node */
|
|
|
|
|
static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeLink *link;
|
|
|
|
|
|
|
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
|
|
|
|
|
|
|
|
|
for (link = node->internal_links.first; link; link = link->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
|
|
|
|
|
node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -892,10 +888,9 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
|
|
|
|
|
float xscale = xrect / ((float)preview->xsize);
|
|
|
|
|
float yscale = yrect / ((float)preview->ysize);
|
|
|
|
|
float scale;
|
|
|
|
|
rctf draw_rect;
|
|
|
|
|
|
|
|
|
|
/* uniform scale and offset */
|
|
|
|
|
draw_rect = *prv;
|
|
|
|
|
rctf draw_rect = *prv;
|
|
|
|
|
if (xscale < yscale) {
|
|
|
|
|
float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
|
|
|
|
|
draw_rect.ymin += offset;
|
|
|
|
@ -1127,14 +1122,9 @@ static void node_draw_basis(const bContext *C,
|
|
|
|
|
bNode *node,
|
|
|
|
|
bNodeInstanceKey key)
|
|
|
|
|
{
|
|
|
|
|
bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
|
|
|
|
|
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 = ®ion->v2d;
|
|
|
|
|
|
|
|
|
|
/* skip if out of view */
|
|
|
|
@ -1147,6 +1137,8 @@ static void node_draw_basis(const bContext *C,
|
|
|
|
|
/* 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);
|
|
|
|
@ -1160,12 +1152,13 @@ static void node_draw_basis(const bContext *C,
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
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;
|
|
|
|
|
float iconofs = rct->xmax - 0.35f * U.widget_unit;
|
|
|
|
|
|
|
|
|
|
/* preview */
|
|
|
|
|
if (node->typeinfo->flag & NODE_PREVIEW) {
|
|
|
|
@ -1273,6 +1266,7 @@ static void node_draw_basis(const bContext *C,
|
|
|
|
|
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,
|
|
|
|
@ -1334,6 +1328,7 @@ static void node_draw_basis(const bContext *C,
|
|
|
|
|
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)) {
|
|
|
|
@ -1356,20 +1351,20 @@ static void node_draw_hidden(const bContext *C,
|
|
|
|
|
bNodeInstanceKey UNUSED(key))
|
|
|
|
|
{
|
|
|
|
|
rctf *rct = &node->totr;
|
|
|
|
|
float dx, centy = BLI_rctf_cent_y(rct);
|
|
|
|
|
float centy = BLI_rctf_cent_y(rct);
|
|
|
|
|
float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
|
|
|
|
|
int color_id = node_get_colorid(node);
|
|
|
|
|
float color[4];
|
|
|
|
|
char showname[128]; /* 128 is used below */
|
|
|
|
|
|
|
|
|
|
View2D *v2d = ®ion->v2d;
|
|
|
|
|
float scale;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
@ -1448,6 +1443,7 @@ static void node_draw_hidden(const bContext *C,
|
|
|
|
|
node_draw_mute_line(®ion->v2d, snode, node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char showname[128]; /* 128 is used below */
|
|
|
|
|
nodeLabel(ntree, node, showname, sizeof(showname));
|
|
|
|
|
|
|
|
|
|
/* XXX - don't print into self! */
|
|
|
|
@ -1477,7 +1473,7 @@ static void node_draw_hidden(const bContext *C,
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
|
|
|
|
|
|
|
|
|
immUniformThemeColorShade(color_id, -10);
|
|
|
|
|
dx = 10.0f;
|
|
|
|
|
float dx = 10.0f;
|
|
|
|
|
|
|
|
|
|
immBegin(GPU_PRIM_LINES, 4);
|
|
|
|
|
immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
|
|
|
|
@ -1573,13 +1569,11 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
bNode *node;
|
|
|
|
|
|
|
|
|
|
/* make sure socket "used" tags are correct, for displaying value buttons */
|
|
|
|
|
ntreeTagUsedSockets(ntree);
|
|
|
|
|
|
|
|
|
|
/* update nodes front to back, so children sizes get updated before parents */
|
|
|
|
|
for (node = ntree->nodes.last; node; node = node->prev) {
|
|
|
|
|
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) {
|
|
|
|
|
node_update(C, ntree, node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1604,10 +1598,6 @@ void node_draw_nodetree(const bContext *C,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
bNodeInstanceKey parent_key)
|
|
|
|
|
{
|
|
|
|
|
bNode *node;
|
|
|
|
|
bNodeLink *link;
|
|
|
|
|
int a;
|
|
|
|
|
|
|
|
|
|
if (ntree == NULL) {
|
|
|
|
|
return; /* groups... */
|
|
|
|
|
}
|
|
|
|
@ -1619,6 +1609,8 @@ void node_draw_nodetree(const bContext *C,
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* draw background nodes, last nodes in front */
|
|
|
|
|
int a;
|
|
|
|
|
bNode *node;
|
|
|
|
|
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
|
|
|
|
|
bNodeInstanceKey key;
|
|
|
|
|
|
|
|
|
@ -1640,7 +1632,7 @@ void node_draw_nodetree(const bContext *C,
|
|
|
|
|
/* node lines */
|
|
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
|
|
|
|
nodelink_batch_start(snode);
|
|
|
|
|
for (link = ntree->links.first; link; link = link->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
|
|
|
|
if (!nodeLinkIsHidden(link)) {
|
|
|
|
|
node_draw_link(®ion->v2d, snode, link);
|
|
|
|
|
}
|
|
|
|
|