2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2007 Blender Foundation. All rights reserved. */
|
2007-04-04 13:58:12 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup nodes
|
2011-02-27 20:13:22 +00:00
|
|
|
*/
|
|
|
|
|
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
#include <ctype.h>
|
2012-08-09 11:45:54 +00:00
|
|
|
#include <limits.h>
|
2013-03-18 16:34:57 +00:00
|
|
|
#include <string.h>
|
2011-02-27 20:13:22 +00:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
2013-11-12 18:17:58 +00:00
|
|
|
#include "BLI_string.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2012-03-17 14:42:44 +00:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BKE_colortools.h"
|
|
|
|
|
#include "BKE_node.h"
|
2021-12-21 15:18:56 +01:00
|
|
|
#include "BKE_node_tree_update.h"
|
2007-04-04 13:58:12 +00:00
|
|
|
|
2011-02-08 12:54:32 +00:00
|
|
|
#include "RNA_access.h"
|
|
|
|
|
#include "RNA_enum_types.h"
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2021-11-17 11:52:44 +01:00
|
|
|
#include "NOD_common.h"
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "node_util.h"
|
|
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Storage Data
|
|
|
|
|
* \{ */
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2007-04-05 10:49:25 +00:00
|
|
|
void node_free_curves(bNode *node)
|
2007-04-04 13:58:12 +00:00
|
|
|
{
|
2019-08-07 03:21:55 +10:00
|
|
|
BKE_curvemapping_free(node->storage);
|
2007-04-04 13:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_free_standard_storage(bNode *node)
|
|
|
|
|
{
|
2012-05-21 08:10:37 +00:00
|
|
|
if (node->storage) {
|
|
|
|
|
MEM_freeN(node->storage);
|
|
|
|
|
}
|
2007-04-04 13:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:08:25 +02:00
|
|
|
void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
|
2007-04-04 13:58:12 +00:00
|
|
|
{
|
2019-08-07 03:21:55 +10:00
|
|
|
dest_node->storage = BKE_curvemapping_copy(src_node->storage);
|
2007-04-04 13:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:08:25 +02:00
|
|
|
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree),
|
|
|
|
|
bNode *dest_node,
|
|
|
|
|
const bNode *src_node)
|
2007-04-04 13:58:12 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
dest_node->storage = MEM_dupallocN(src_node->storage);
|
2007-04-04 13:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void *node_initexec_curves(bNodeExecContext *UNUSED(context),
|
|
|
|
|
bNode *node,
|
|
|
|
|
bNodeInstanceKey UNUSED(key))
|
2012-08-29 07:58:36 +00:00
|
|
|
{
|
2020-08-01 13:02:21 +10:00
|
|
|
BKE_curvemapping_init(node->storage);
|
2012-08-29 07:58:36 +00:00
|
|
|
return NULL; /* unused return */
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Updates
|
|
|
|
|
* \{ */
|
2020-02-11 15:31:40 +00:00
|
|
|
|
|
|
|
|
void node_sock_label(bNodeSocket *sock, const char *name)
|
|
|
|
|
{
|
|
|
|
|
BLI_strncpy(sock->label, name, MAX_NAME);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-23 09:21:56 +00:00
|
|
|
void node_sock_label_clear(bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
if (sock->label[0] != '\0') {
|
|
|
|
|
sock->label[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-17 11:10:46 +01:00
|
|
|
void node_math_update(bNodeTree *ntree, bNode *node)
|
2020-02-11 15:31:40 +00:00
|
|
|
{
|
|
|
|
|
bNodeSocket *sock1 = BLI_findlink(&node->inputs, 0);
|
|
|
|
|
bNodeSocket *sock2 = BLI_findlink(&node->inputs, 1);
|
|
|
|
|
bNodeSocket *sock3 = BLI_findlink(&node->inputs, 2);
|
2021-11-17 11:10:46 +01:00
|
|
|
nodeSetSocketAvailability(ntree,
|
|
|
|
|
sock2,
|
2020-02-11 15:31:40 +00:00
|
|
|
!ELEM(node->custom1,
|
|
|
|
|
NODE_MATH_SQRT,
|
|
|
|
|
NODE_MATH_SIGN,
|
|
|
|
|
NODE_MATH_CEIL,
|
|
|
|
|
NODE_MATH_SINE,
|
|
|
|
|
NODE_MATH_ROUND,
|
|
|
|
|
NODE_MATH_FLOOR,
|
|
|
|
|
NODE_MATH_COSINE,
|
|
|
|
|
NODE_MATH_ARCSINE,
|
|
|
|
|
NODE_MATH_TANGENT,
|
|
|
|
|
NODE_MATH_ABSOLUTE,
|
|
|
|
|
NODE_MATH_RADIANS,
|
|
|
|
|
NODE_MATH_DEGREES,
|
|
|
|
|
NODE_MATH_FRACTION,
|
|
|
|
|
NODE_MATH_ARCCOSINE,
|
|
|
|
|
NODE_MATH_ARCTANGENT) &&
|
|
|
|
|
!ELEM(node->custom1,
|
|
|
|
|
NODE_MATH_INV_SQRT,
|
|
|
|
|
NODE_MATH_TRUNC,
|
|
|
|
|
NODE_MATH_EXPONENT,
|
|
|
|
|
NODE_MATH_COSH,
|
|
|
|
|
NODE_MATH_SINH,
|
|
|
|
|
NODE_MATH_TANH));
|
2021-11-17 11:10:46 +01:00
|
|
|
nodeSetSocketAvailability(ntree,
|
|
|
|
|
sock3,
|
2020-02-11 15:31:40 +00:00
|
|
|
ELEM(node->custom1,
|
|
|
|
|
NODE_MATH_COMPARE,
|
|
|
|
|
NODE_MATH_MULTIPLY_ADD,
|
|
|
|
|
NODE_MATH_WRAP,
|
|
|
|
|
NODE_MATH_SMOOTH_MIN,
|
|
|
|
|
NODE_MATH_SMOOTH_MAX));
|
|
|
|
|
|
2021-03-23 09:21:56 +00:00
|
|
|
node_sock_label_clear(sock1);
|
|
|
|
|
node_sock_label_clear(sock2);
|
|
|
|
|
node_sock_label_clear(sock3);
|
2020-02-11 15:31:40 +00:00
|
|
|
|
|
|
|
|
switch (node->custom1) {
|
|
|
|
|
case NODE_MATH_WRAP:
|
2021-05-12 11:15:56 +01:00
|
|
|
node_sock_label(sock2, "Max");
|
|
|
|
|
node_sock_label(sock3, "Min");
|
2020-02-11 15:31:40 +00:00
|
|
|
break;
|
|
|
|
|
case NODE_MATH_MULTIPLY_ADD:
|
|
|
|
|
node_sock_label(sock2, "Multiplier");
|
|
|
|
|
node_sock_label(sock3, "Addend");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_LESS_THAN:
|
|
|
|
|
case NODE_MATH_GREATER_THAN:
|
|
|
|
|
node_sock_label(sock2, "Threshold");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_PINGPONG:
|
|
|
|
|
node_sock_label(sock2, "Scale");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_SNAP:
|
|
|
|
|
node_sock_label(sock2, "Increment");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_POWER:
|
|
|
|
|
node_sock_label(sock1, "Base");
|
|
|
|
|
node_sock_label(sock2, "Exponent");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_LOGARITHM:
|
|
|
|
|
node_sock_label(sock2, "Base");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_DEGREES:
|
|
|
|
|
node_sock_label(sock1, "Radians");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_RADIANS:
|
|
|
|
|
node_sock_label(sock1, "Degrees");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_COMPARE:
|
|
|
|
|
node_sock_label(sock3, "Epsilon");
|
|
|
|
|
break;
|
|
|
|
|
case NODE_MATH_SMOOTH_MAX:
|
|
|
|
|
case NODE_MATH_SMOOTH_MIN:
|
|
|
|
|
node_sock_label(sock3, "Distance");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Labels
|
|
|
|
|
* \{ */
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void node_blend_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
|
2011-02-08 12:54:32 +00:00
|
|
|
{
|
|
|
|
|
const char *name;
|
2019-11-06 14:19:58 +00:00
|
|
|
bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, node->custom1, &name);
|
|
|
|
|
if (!enum_label) {
|
|
|
|
|
name = "Unknown";
|
|
|
|
|
}
|
2013-11-12 18:17:58 +00:00
|
|
|
BLI_strncpy(label, IFACE_(name), maxlen);
|
2011-02-08 12:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void node_image_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
|
2018-01-07 22:29:25 +01:00
|
|
|
{
|
2019-04-29 20:12:09 +10:00
|
|
|
/* If there is no loaded image, return an empty string,
|
|
|
|
|
* and let nodeLabel() fill in the proper type translation. */
|
2018-01-07 22:29:25 +01:00
|
|
|
BLI_strncpy(label, (node->id) ? node->id->name + 2 : "", maxlen);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void node_math_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
|
2011-02-08 12:54:32 +00:00
|
|
|
{
|
|
|
|
|
const char *name;
|
2019-11-06 14:19:58 +00:00
|
|
|
bool enum_label = RNA_enum_name(rna_enum_node_math_items, node->custom1, &name);
|
|
|
|
|
if (!enum_label) {
|
|
|
|
|
name = "Unknown";
|
|
|
|
|
}
|
2013-11-12 18:17:58 +00:00
|
|
|
BLI_strncpy(label, IFACE_(name), maxlen);
|
2011-02-08 12:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void node_vector_math_label(const bNodeTree *UNUSED(ntree),
|
|
|
|
|
const bNode *node,
|
|
|
|
|
char *label,
|
|
|
|
|
int maxlen)
|
2011-02-08 12:54:32 +00:00
|
|
|
{
|
|
|
|
|
const char *name;
|
2019-11-06 14:19:58 +00:00
|
|
|
bool enum_label = RNA_enum_name(rna_enum_node_vec_math_items, node->custom1, &name);
|
|
|
|
|
if (!enum_label) {
|
|
|
|
|
name = "Unknown";
|
|
|
|
|
}
|
2013-11-12 18:17:58 +00:00
|
|
|
BLI_strncpy(label, IFACE_(name), maxlen);
|
2011-02-08 12:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void node_filter_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
|
2011-02-08 12:54:32 +00:00
|
|
|
{
|
|
|
|
|
const char *name;
|
2019-11-06 14:19:58 +00:00
|
|
|
bool enum_label = RNA_enum_name(rna_enum_node_filter_items, node->custom1, &name);
|
|
|
|
|
if (!enum_label) {
|
|
|
|
|
name = "Unknown";
|
|
|
|
|
}
|
2013-11-12 18:17:58 +00:00
|
|
|
BLI_strncpy(label, IFACE_(name), maxlen);
|
2011-02-08 12:54:32 +00:00
|
|
|
}
|
2011-11-20 16:38:23 +00:00
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Link Insertion
|
|
|
|
|
* \{ */
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
static bool node_link_socket_match(const bNodeSocket *a, const bNodeSocket *b)
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
{
|
2021-04-07 00:26:03 -05:00
|
|
|
/* Check if sockets are of the same type. */
|
2018-03-19 21:30:33 +01:00
|
|
|
if (a->typeinfo != b->typeinfo) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
/* Test if alphabetic prefix matches, allowing for imperfect matches, such as numeric suffixes
|
|
|
|
|
* like Color1/Color2. */
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
int prefix_len = 0;
|
2021-04-07 00:26:03 -05:00
|
|
|
const char *ca = a->name, *cb = b->name;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (; *ca != '\0' && *cb != '\0'; ca++, cb++) {
|
2021-04-07 00:26:03 -05:00
|
|
|
/* End of common prefix? */
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
if (*ca != *cb) {
|
2021-04-07 00:26:03 -05:00
|
|
|
/* Prefix delimited by non-alphabetic char. */
|
2019-04-22 13:31:31 +10:00
|
|
|
if (isalpha(*ca) || isalpha(*cb)) {
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
return false;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
prefix_len++;
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
}
|
|
|
|
|
return prefix_len > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
{
|
|
|
|
|
int count = 0;
|
2021-04-07 00:26:03 -05:00
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
|
|
|
|
if (ELEM(socket, link->fromsock, link->tosock)) {
|
2019-09-08 00:12:26 +10:00
|
|
|
count++;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree,
|
|
|
|
|
bNode *node,
|
|
|
|
|
bNodeSocket *to_socket)
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
{
|
2021-04-07 00:26:03 -05:00
|
|
|
bNodeSocket *first = to_socket->in_out == SOCK_IN ? node->inputs.first : node->outputs.first;
|
|
|
|
|
|
|
|
|
|
/* Wrap around the list end. */
|
|
|
|
|
bNodeSocket *socket_iter = to_socket->next ? to_socket->next : first;
|
|
|
|
|
while (socket_iter != to_socket) {
|
|
|
|
|
if (!nodeSocketIsHidden(socket_iter) && node_link_socket_match(socket_iter, to_socket)) {
|
|
|
|
|
const int link_count = node_count_links(ntree, socket_iter);
|
|
|
|
|
/* Add one to account for the new link being added. */
|
|
|
|
|
if (link_count + 1 <= nodeSocketLinkLimit(socket_iter)) {
|
|
|
|
|
return socket_iter; /* Found a valid free socket we can swap to. */
|
|
|
|
|
}
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
}
|
2021-04-07 00:26:03 -05:00
|
|
|
socket_iter = socket_iter->next ? socket_iter->next : first; /* Wrap around the list end. */
|
2021-02-03 11:02:01 -06:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
|
|
|
|
|
{
|
2021-04-07 00:26:03 -05:00
|
|
|
bNodeSocket *socket = link->tosock;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 13:31:31 +10:00
|
|
|
if (node != link->tonode) {
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
return;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-07 00:32:16 -05:00
|
|
|
/* If we're not at the link limit of the target socket, we can skip
|
|
|
|
|
* trying to move existing links to another socket. */
|
|
|
|
|
const int to_link_limit = nodeSocketLinkLimit(socket);
|
|
|
|
|
if (socket->total_inputs + 1 < to_link_limit) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, to_link, &ntree->links) {
|
|
|
|
|
if (socket == to_link->tosock) {
|
|
|
|
|
bNodeSocket *new_socket = node_find_linkable_socket(ntree, node, socket);
|
|
|
|
|
if (new_socket && new_socket != socket) {
|
|
|
|
|
/* Attempt to redirect the existing link to the new socket. */
|
|
|
|
|
to_link->tosock = new_socket;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-07 00:26:03 -05:00
|
|
|
if (new_socket == NULL) {
|
|
|
|
|
/* No possible replacement, remove the existing link. */
|
|
|
|
|
nodeRemLink(ntree, to_link);
|
|
|
|
|
return;
|
|
|
|
|
}
|
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
2015-12-03 12:51:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/** \} */
|
2014-03-02 16:04:25 +01:00
|
|
|
|
2020-11-06 16:14:43 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Default value RNA access
|
|
|
|
|
* \{ */
|
2014-03-02 16:04:25 +01:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
return RNA_float_get(&ptr, "default_value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
RNA_float_set(&ptr, "default_value", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
RNA_float_get_array(&ptr, "default_value", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_socket_set_color(bNodeTree *ntree,
|
|
|
|
|
bNode *UNUSED(node),
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
const float *value)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
RNA_float_set_array(&ptr, "default_value", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
RNA_float_get_array(&ptr, "default_value", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_socket_set_vector(bNodeTree *ntree,
|
|
|
|
|
bNode *UNUSED(node),
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
const float *value)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
|
|
|
|
|
RNA_float_set_array(&ptr, "default_value", value);
|
|
|
|
|
}
|
2020-11-06 16:14:43 +11:00
|
|
|
|
|
|
|
|
/** \} */
|