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:
authorCharlie Jolly <charlie>2021-03-16 22:11:54 +0300
committerCharlie Jolly <mistajolly@gmail.com>2021-03-17 14:54:16 +0300
commit266cd7bb82ce4bfed20a3d61a84f25e2bacfca2b (patch)
tree963a983f902f5368669c1d93312b53262592e4dc /source/blender/blenkernel/intern
parent20bf736ff81c6fb79558796b74d50d4e7a9c8ef6 (diff)
Nodes: Add support to mute node wires
This patch adds the ability to mute individual wires in the node editor. This is invoked like the cut links operator but with a new shortcut. Mute = Ctrl + Alt Cut = Ctrl Dragging over wires will toggle the mute state for that wire. The muted wires are drawn in red with a bar across the center. Red is used in the nodes context to indicate invalid links, muted links and internal links. When a wire is muted it exposes the original node buttons which are normally hidden when a wire is connected. Downstream and upstream links connected using reroute nodes are also muted. Outside scope of patch: - Add support for pynodes e.g. Animation Nodes - Requires minor change to check for muted links using the `is_muted` link property or the `is_linked` socket property. Maniphest Tasks: T52659 Differential Revision: https://developer.blender.org/D2807
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/node.cc111
1 files changed, 110 insertions, 1 deletions
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index bbc655d7fc8..ca973bd9d65 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -107,6 +107,9 @@ static void node_free_node(bNodeTree *ntree, bNode *node);
static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
bNodeSocket *sock,
const bool do_id_user);
+static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
+ struct bNode *node,
+ const bool mute);
static void ntree_init_data(ID *id)
{
@@ -2215,6 +2218,106 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
}
}
+/* Check if all output links are muted or not. */
+static bool nodeMuteFromSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock)
+{
+ int tot = 0;
+ int muted = 0;
+ LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sock) {
+ tot++;
+ if (link->flag & NODE_LINK_MUTED) {
+ muted++;
+ }
+ }
+ }
+ return tot == muted;
+}
+
+static void nodeMuteLink(bNodeLink *link)
+{
+ link->flag |= NODE_LINK_MUTED;
+ link->flag |= NODE_LINK_TEST;
+ if (!(link->tosock->flag & SOCK_MULTI_INPUT)) {
+ link->tosock->flag &= ~SOCK_IN_USE;
+ }
+}
+
+static void nodeUnMuteLink(bNodeLink *link)
+{
+ link->flag &= ~NODE_LINK_MUTED;
+ link->flag |= NODE_LINK_TEST;
+ link->tosock->flag |= SOCK_IN_USE;
+}
+
+/* Upstream muting. Always happens when unmuting but checks when muting. O(n^2) algorithm.*/
+static void nodeMuteRerouteInputLinks(bNodeTree *ntree, bNode *node, const bool mute)
+{
+ if (node->type != NODE_REROUTE) {
+ return;
+ }
+ if (!mute || nodeMuteFromSocketLinks(ntree, (bNodeSocket *)node->outputs.first)) {
+ bNodeSocket *sock = (bNodeSocket *)node->inputs.first;
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+ if (!(link->flag & NODE_LINK_VALID) || (link->tosock != sock)) {
+ continue;
+ }
+ if (mute) {
+ nodeMuteLink(link);
+ }
+ else {
+ nodeUnMuteLink(link);
+ }
+ nodeMuteRerouteInputLinks(ntree, link->fromnode, mute);
+ }
+ }
+}
+
+/* Downstream muting propagates when reaching reroute nodes. O(n^2) algorithm.*/
+static void nodeMuteRerouteOutputLinks(bNodeTree *ntree, bNode *node, const bool mute)
+{
+ if (node->type != NODE_REROUTE) {
+ return;
+ }
+ bNodeSocket *sock;
+ sock = (bNodeSocket *)node->outputs.first;
+ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+ if (!(link->flag & NODE_LINK_VALID) || (link->fromsock != sock)) {
+ continue;
+ }
+ if (mute) {
+ nodeMuteLink(link);
+ }
+ else {
+ nodeUnMuteLink(link);
+ }
+ nodeMuteRerouteOutputLinks(ntree, link->tonode, mute);
+ }
+}
+
+void nodeMuteLinkToggle(bNodeTree *ntree, bNodeLink *link)
+{
+ if (link->tosock) {
+ bool mute = !(link->flag & NODE_LINK_MUTED);
+ if (mute) {
+ nodeMuteLink(link);
+ }
+ else {
+ nodeUnMuteLink(link);
+ }
+ if (link->tonode->type == NODE_REROUTE) {
+ nodeMuteRerouteOutputLinks(ntree, link->tonode, mute);
+ }
+ if (link->fromnode->type == NODE_REROUTE) {
+ nodeMuteRerouteInputLinks(ntree, link->fromnode, mute);
+ }
+ }
+
+ if (ntree) {
+ ntree->update |= NTREE_UPDATE_LINKS;
+ }
+}
+
void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
@@ -2257,6 +2360,10 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
link->flag &= ~NODE_LINK_VALID;
}
+ if (fromlink->flag & NODE_LINK_MUTED) {
+ link->flag |= NODE_LINK_MUTED;
+ }
+
ntree->update |= NTREE_UPDATE_LINKS;
}
else {
@@ -4014,7 +4121,9 @@ void ntreeTagUsedSockets(bNodeTree *ntree)
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
link->fromsock->flag |= SOCK_IN_USE;
- link->tosock->flag |= SOCK_IN_USE;
+ if (!(link->flag & NODE_LINK_MUTED)) {
+ link->tosock->flag |= SOCK_IN_USE;
+ }
}
}