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:
-rw-r--r--release/scripts/startup/nodeitems_builtins.py45
-rw-r--r--source/blender/makesdna/DNA_node_types.h5
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c16
-rw-r--r--source/blender/nodes/intern/node_common.c169
5 files changed, 131 insertions, 105 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 09820291222..f130a79ede0 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -94,9 +94,6 @@ def node_group_items(context):
yield NodeItemCustom(draw=group_tools_draw)
- yield NodeItem("NodeGroupInput", poll=group_input_output_item_poll)
- yield NodeItem("NodeGroupOutput", poll=group_input_output_item_poll)
-
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
def contains_group(nodetree, group):
@@ -123,6 +120,40 @@ def node_group_items(context):
settings={"node_tree": "bpy.data.node_groups[%r]" % group.name})
+def node_group_input_items(context):
+ if context is None:
+ return
+ space = context.space_data
+ if not space:
+ return
+ ntree = space.edit_tree
+ if not ntree:
+ return
+
+ for i, iosock in enumerate(ntree.inputs):
+ settings = dict()
+ settings["use_extension_socket"] = "False"
+ for k, _ in enumerate(ntree.inputs):
+ settings["outputs[{}].hide".format(k)] = "False" if k == i else "True"
+ yield NodeItem("NodeGroupInput", label=iosock.name, settings=settings, poll=group_input_output_item_poll)
+
+
+def node_group_output_items(context):
+ if context is None:
+ return
+ space = context.space_data
+ if not space:
+ return
+ ntree = space.edit_tree
+ if not ntree:
+ return
+
+ # Node groups are not added as single-socket nodes currently, because only one node can be active output.
+ # Dividing group output between multiple nodes will require changes to the "active output" concept (NODE_DO_OUTPUT flag).
+
+ yield NodeItem("NodeGroupOutput", poll=group_input_output_item_poll)
+
+
# only show input/output nodes inside node groups
def group_input_output_item_poll(context):
space = context.space_data
@@ -294,6 +325,8 @@ shader_node_categories = [
NodeItem("ShaderNodeScript"),
]),
ShaderNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
+ ShaderNodeCategory("SH_NEW_GROUP_INPUTS", "Group Inputs", items=node_group_input_items),
+ ShaderNodeCategory("SH_NEW_GROUP_OUTPUTS", "Group Outputs", items=node_group_output_items),
ShaderNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
NodeItem("NodeReroute"),
@@ -409,6 +442,8 @@ compositor_node_categories = [
NodeItem("CompositorNodeCornerPin"),
]),
CompositorNodeCategory("CMP_GROUP", "Group", items=node_group_items),
+ CompositorNodeCategory("CMP_GROUP_INPUTS", "Group Inputs", items=node_group_input_items),
+ CompositorNodeCategory("CMP_GROUP_OUTPUTS", "Group Outputs", items=node_group_output_items),
CompositorNodeCategory("CMP_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
NodeItem("NodeReroute"),
@@ -466,6 +501,8 @@ texture_node_categories = [
NodeItem("TextureNodeAt"),
]),
TextureNodeCategory("TEX_GROUP", "Group", items=node_group_items),
+ TextureNodeCategory("TEX_GROUP_INPUTS", "Group Inputs", items=node_group_input_items),
+ TextureNodeCategory("TEX_GROUP_OUTPUTS", "Group Outputs", items=node_group_output_items),
TextureNodeCategory("TEX_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
NodeItem("NodeReroute"),
@@ -596,6 +633,8 @@ geometry_node_categories = [
NodeItem("GeometryNodeVolumeToMesh"),
]),
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
+ GeometryNodeCategory("GEO_GROUP_INPUTS", "Group Inputs", items=node_group_input_items),
+ GeometryNodeCategory("GEO_GROUP_OUTPUTS", "Group Outputs", items=node_group_output_items),
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
NodeItem("NodeReroute"),
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 5152098f57a..5c3cf3f340a 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -616,6 +616,11 @@ typedef struct bNodeSocketValueMaterial {
} bNodeSocketValueMaterial;
/* Data structs, for node->storage. */
+
+typedef enum eNodeGroupInputOutputFlags {
+ NODE_GROUP_USE_EXTENSION_SOCKET = 1,
+} eNodeGroupInputOutputFlags;
+
enum {
CMP_NODE_MASKTYPE_ADD = 0,
CMP_NODE_MASKTYPE_SUBTRACT = 1,
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 97615016016..08504b0d8c4 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -453,6 +453,7 @@ extern StructRNA RNA_NodeOutputFileSlotLayer;
extern StructRNA RNA_NodeSocket;
extern StructRNA RNA_NodeSocketInterface;
extern StructRNA RNA_NodeSocketStandard;
+extern StructRNA RNA_NodeSocketVirtual;
extern StructRNA RNA_NodeTree;
extern StructRNA RNA_NoiseGpencilModifier;
extern StructRNA RNA_NoiseTexture;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 3d4256db335..9696b05cf71 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4650,6 +4650,13 @@ static void def_group_input(StructRNA *srna)
RNA_def_property_struct_type(prop, "PropertyGroup");
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
+
+ prop = RNA_def_property(srna, "use_extension_socket", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", NODE_GROUP_USE_EXTENSION_SOCKET);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(
+ prop, "Use Extension Socket", "Add a virtual socket to the node for extending the node group interface");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_group_output(StructRNA *srna)
@@ -4663,6 +4670,15 @@ static void def_group_output(StructRNA *srna)
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
+ prop = RNA_def_property(srna, "use_extension_socket", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", NODE_GROUP_USE_EXTENSION_SOCKET);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(
+ prop,
+ "Use Extension Socket",
+ "Add a virtual socket to the node for extending the node group interface");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
prop = RNA_def_property(srna, "is_active_output", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT);
RNA_def_property_ui_text(
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index b8c89d1db37..ef0bc18a49c 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -34,6 +34,7 @@
#include "BKE_node.h"
+#include "RNA_access.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
@@ -432,33 +433,25 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
/** \name Node #GROUP_INPUT / #GROUP_OUTPUT
* \{ */
-static void node_group_input_init(bNodeTree *ntree, bNode *node)
-{
- node_group_input_update(ntree, node);
-}
-
-bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
+/* Check if the extension socket is connected and expose internal sockets. */
+static void node_group_handle_extension(bNodeTree *ntree, bNode *node, ListBase *socket_list)
{
- bNodeSocket *sock;
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (STREQ(sock->identifier, identifier)) {
- return sock;
- }
+ bNodeSocket *extsock = socket_list->last;
+ if (!extsock) {
+ /* Can be called during initial update before the extension socket is added. */
+ return;
}
- return NULL;
-}
+ /* This function should only be called when virtual sockets are enabled. */
+ BLI_assert(RNA_struct_is_a(extsock->typeinfo->ext_socket.srna, &RNA_NodeSocketVirtual));
-void node_group_input_update(bNodeTree *ntree, bNode *node)
-{
- bNodeSocket *extsock = node->outputs.last;
- bNodeLink *link, *linknext, *exposelink;
+ bNodeLink *link, *linknext;
/* Adding a tree socket and verifying will remove the extension socket!
* This list caches the existing links from the extension socket
* so they can be recreated after verification.
*/
ListBase tmplinks;
- /* find links from the extension socket and store them */
+ /* Find links from the extension socket and store them. */
BLI_listbase_clear(&tmplinks);
for (link = ntree->links.first; link; link = linknext) {
linknext = link->next;
@@ -466,7 +459,8 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
continue;
}
- if (link->fromsock == extsock) {
+ /* Check both fromsock and tosock so it works for input as well as outputs. */
+ if (link->fromsock == extsock || link->tosock == extsock) {
bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
*tlink = *link;
BLI_addtail(&tmplinks, tlink);
@@ -475,42 +469,69 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
}
}
- /* find valid link to expose */
- exposelink = NULL;
+ /* Find valid link to expose. */
+ bNode *expose_node = NULL;
+ bNodeSocket *expose_sock = NULL;
for (link = tmplinks.first; link; link = link->next) {
- /* XXX Multiple sockets can be connected to the extension socket at once,
+ /* Multiple sockets can be connected to the extension socket at once,
* in that case the arbitrary first link determines name and type.
* This could be improved by choosing the "best" type among all links,
* whatever that means.
*/
- if (link->tosock->type != SOCK_CUSTOM) {
- exposelink = link;
+ if (link->fromsock == extsock && link->tosock->type != SOCK_CUSTOM) {
+ expose_node = link->tonode;
+ expose_sock = link->tosock;
+ }
+ else if (link->tosock == extsock && link->fromsock->type != SOCK_CUSTOM) {
+ expose_node = link->fromnode;
+ expose_sock = link->fromsock;
break;
}
}
- if (exposelink) {
+ if (expose_node && expose_sock) {
bNodeSocket *gsock, *newsock;
- gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock);
+ gsock = ntreeAddSocketInterfaceFromSocket(ntree, expose_node, expose_sock);
- node_group_input_update(ntree, node);
- newsock = node_group_input_find_socket(node, gsock->identifier);
+ if (node->typeinfo->updatefunc) {
+ node->typeinfo->updatefunc(ntree, node);
+ }
+ newsock = BLI_findstring(socket_list, gsock->identifier, offsetof(bNodeSocket, identifier));
/* redirect links from the extension socket */
for (link = tmplinks.first; link; link = link->next) {
- nodeAddLink(ntree, node, newsock, link->tonode, link->tosock);
+ nodeAddLink(ntree, node, newsock, expose_node, expose_sock);
}
}
BLI_freelistN(&tmplinks);
+}
- /* check inputs and outputs, and remove or insert them */
- {
- /* value_in_out inverted for interface nodes to get correct socket value_property */
- group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
+bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
+{
+ return BLI_findstring(&node->outputs, identifier, offsetof(bNodeSocket, identifier));
+}
+
+static void node_group_input_init(bNodeTree *ntree, bNode *node)
+{
+ node_group_input_update(ntree, node);
+}
+
+void node_group_input_update(bNodeTree *ntree, bNode *node)
+{
+ const bool use_extension_socket = node->custom1 & NODE_GROUP_USE_EXTENSION_SOCKET;
+
+ if (use_extension_socket) {
+ node_group_handle_extension(ntree, node, &node->outputs);
+ }
+
+ /* Check group tree interface and remove or insert sockets as needed. */
+ /* SOCK_IN/SOCK_OUT is inverted for interface nodes: Group input nodes have output sockets. */
+ group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
- /* add virtual extension socket */
+ if (use_extension_socket) {
+ /* Add virtual extension socket. */
nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", "");
}
}
@@ -529,86 +550,30 @@ void register_node_type_group_input(void)
nodeRegisterType(ntype);
}
-static void node_group_output_init(bNodeTree *ntree, bNode *node)
+bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
{
- node_group_output_update(ntree, node);
+ return BLI_findstring(&node->inputs, identifier, offsetof(bNodeSocket, identifier));
}
-bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
+static void node_group_output_init(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock;
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (STREQ(sock->identifier, identifier)) {
- return sock;
- }
- }
- return NULL;
+ node_group_output_update(ntree, node);
}
void node_group_output_update(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *extsock = node->inputs.last;
- bNodeLink *link, *linknext, *exposelink;
- /* Adding a tree socket and verifying will remove the extension socket!
- * This list caches the existing links to the extension socket
- * so they can be recreated after verification.
- */
- ListBase tmplinks;
+ const bool use_extension_socket = node->custom1 & NODE_GROUP_USE_EXTENSION_SOCKET;
- /* find links to the extension socket and store them */
- BLI_listbase_clear(&tmplinks);
- for (link = ntree->links.first; link; link = linknext) {
- linknext = link->next;
- if (nodeLinkIsHidden(link)) {
- continue;
- }
-
- if (link->tosock == extsock) {
- bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
- *tlink = *link;
- BLI_addtail(&tmplinks, tlink);
-
- nodeRemLink(ntree, link);
- }
+ if (use_extension_socket) {
+ node_group_handle_extension(ntree, node, &node->inputs);
}
- /* find valid link to expose */
- exposelink = NULL;
- for (link = tmplinks.first; link; link = link->next) {
- /* XXX Multiple sockets can be connected to the extension socket at once,
- * in that case the arbitrary first link determines name and type.
- * This could be improved by choosing the "best" type among all links,
- * whatever that means.
- */
- if (link->fromsock->type != SOCK_CUSTOM) {
- exposelink = link;
- break;
- }
- }
-
- if (exposelink) {
- bNodeSocket *gsock, *newsock;
-
- /* XXX what if connecting virtual to virtual socket?? */
- gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock);
-
- node_group_output_update(ntree, node);
- newsock = node_group_output_find_socket(node, gsock->identifier);
-
- /* redirect links to the extension socket */
- for (link = tmplinks.first; link; link = link->next) {
- nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock);
- }
- }
-
- BLI_freelistN(&tmplinks);
-
- /* check inputs and outputs, and remove or insert them */
- {
- /* value_in_out inverted for interface nodes to get correct socket value_property */
- group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
+ /* Check group tree interface and remove or insert sockets as needed. */
+ /* SOCK_IN/SOCK_OUT is inverted for interface nodes: Group output nodes have input sockets. */
+ group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
- /* add virtual extension socket */
+ if (use_extension_socket) {
+ /* Add virtual extension socket */
nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", "");
}
}