[Bf-blender-cvs] [5bfe09df224] master: Geometry Nodes: support viewing field values in spreadsheet

Jacques Lucke noreply at git.blender.org
Tue Oct 26 11:28:04 CEST 2021


Commit: 5bfe09df2244cb9de0b6554a378eecef77b1e75d
Author: Jacques Lucke
Date:   Tue Oct 26 11:25:32 2021 +0200
Branches: master
https://developer.blender.org/rB5bfe09df2244cb9de0b6554a378eecef77b1e75d

Geometry Nodes: support viewing field values in spreadsheet

The viewer node has been expanded to have a field input next to the
geometry input. When both are connected (by ctrl+shift clicking on a node)
the spreadsheet will show the evaluated field on the geometry.

The operator to link to the viewer has become a bit smarter. It automatically
detects if it should link to the geometry or field input. In the future some more
smartness could be added, such as automatically relinking the "right" geometry
when viewing a field.

Internally, there are two major changes:
* Refactor of what happens when ctrl+shift clicking on a node to link to
  a viewer. The behavior of the geometry nodes viewer is a bit more complex
  than that of the compositor viewers. The behavior in compositing nodes
  should not have changed. Any change should be reported as a bug (and then
  we can decide if it's worse than before or if it needs fixing).
*  Evaluation, display and caching of fields in the spreadsheet editor.

Differential Revision: https://developer.blender.org/D12938

===================================================================

M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/space_node/node_relationships.cc
M	source/blender/editors/space_spreadsheet/CMakeLists.txt
M	source/blender/editors/space_spreadsheet/space_spreadsheet.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_cache.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_cache.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/nodes/node_geo_viewer.cc

===================================================================

diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 044659e4fbe..57447db8723 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2100,5 +2100,22 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
       version_geometry_nodes_set_position_node_offset(ntree);
     }
     /* Keep this block, even when empty. */
+
+    /* Add storage to viewer node. */
+    LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+      if (ntree->type != NTREE_GEOMETRY) {
+        continue;
+      }
+      LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+        if (node->type == GEO_NODE_VIEWER) {
+          if (node->storage == NULL) {
+            NodeGeometryViewer *data = (NodeGeometryViewer *)MEM_callocN(
+                sizeof(NodeGeometryViewer), __func__);
+            data->data_type = CD_PROP_FLOAT;
+            node->storage = data;
+          }
+        }
+      }
+    }
   }
 }
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index b69e7e98bca..459608a67ea 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -57,8 +57,12 @@
 
 #include "BLT_translation.h"
 
+#include "NOD_node_tree_ref.hh"
+
 #include "node_intern.h" /* own include */
 
+using namespace blender::nodes::node_tree_ref_types;
+
 /* -------------------------------------------------------------------- */
 /** \name Relations Helpers
  * \{ */
@@ -612,160 +616,274 @@ static void snode_autoconnect(Main *bmain,
 /** \name Link Viewer Operator
  * \{ */
 
-static int node_link_viewer(const bContext *C, bNode *tonode)
-{
-  SpaceNode *snode = CTX_wm_space_node(C);
+namespace blender::ed::nodes::viewer_linking {
 
-  /* context check */
-  if (tonode == nullptr || BLI_listbase_is_empty(&tonode->outputs)) {
-    return OPERATOR_CANCELLED;
+/* Depending on the node tree type, different socket types are supported by viewer nodes. */
+static bool socket_can_be_viewed(const OutputSocketRef &socket)
+{
+  if (nodeSocketIsHidden(socket.bsocket())) {
+    return false;
   }
-  if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
-    return OPERATOR_CANCELLED;
+  if (socket.idname() == "NodeSocketVirtual") {
+    return false;
   }
+  if (socket.tree().btree()->type != NTREE_GEOMETRY) {
+    return true;
+  }
+  return ELEM(socket.typeinfo()->type,
+              SOCK_GEOMETRY,
+              SOCK_FLOAT,
+              SOCK_VECTOR,
+              SOCK_INT,
+              SOCK_BOOLEAN,
+              SOCK_RGBA);
+}
 
-  /* get viewer */
-  bNode *viewer_node = nullptr;
-  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
-    if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
-      if (node->flag & NODE_DO_OUTPUT) {
-        viewer_node = node;
-        break;
-      }
-    }
+static CustomDataType socket_type_to_custom_data_type(const eNodeSocketDatatype socket_type)
+{
+  switch (socket_type) {
+    case SOCK_FLOAT:
+      return CD_PROP_FLOAT;
+    case SOCK_INT:
+      return CD_PROP_INT32;
+    case SOCK_VECTOR:
+      return CD_PROP_FLOAT3;
+    case SOCK_BOOLEAN:
+      return CD_PROP_BOOL;
+    case SOCK_RGBA:
+      return CD_PROP_COLOR;
+    default:
+      /* Fallback. */
+      return CD_AUTO_FROM_NAME;
   }
-  /* no viewer, we make one active */
-  if (viewer_node == nullptr) {
-    LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
-      if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
-        node->flag |= NODE_DO_OUTPUT;
-        viewer_node = node;
-        break;
+}
+
+/**
+ * Find the socket to link to in a viewer node.
+ */
+static bNodeSocket *node_link_viewer_get_socket(bNodeTree *ntree,
+                                                bNode *viewer_node,
+                                                bNodeSocket *src_socket)
+{
+  if (viewer_node->type != GEO_NODE_VIEWER) {
+    /* In viewer nodes in the compositor, only the first input should be linked to. */
+    return (bNodeSocket *)viewer_node->inputs.first;
+  }
+  /* For the geometry nodes viewer, find the socket with the correct type. */
+  LISTBASE_FOREACH (bNodeSocket *, viewer_socket, &viewer_node->inputs) {
+    if (viewer_socket->type == src_socket->type) {
+      if (viewer_socket->type == SOCK_GEOMETRY) {
+        return viewer_socket;
       }
+      NodeGeometryViewer *storage = (NodeGeometryViewer *)viewer_node->storage;
+      const CustomDataType data_type = socket_type_to_custom_data_type(
+          (eNodeSocketDatatype)src_socket->type);
+      BLI_assert(data_type != CD_AUTO_FROM_NAME);
+      storage->data_type = data_type;
+      nodeUpdate(ntree, viewer_node);
+      return viewer_socket;
     }
   }
+  return nullptr;
+}
 
-  bNodeSocket *sock = nullptr;
-  bNodeLink *link = nullptr;
-
-  /* try to find an already connected socket to cycle to the next */
-  if (viewer_node) {
-    link = nullptr;
+static bool is_viewer_node(const NodeRef &node)
+{
+  return ELEM(node.bnode()->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER);
+}
 
-    for (link = (bNodeLink *)snode->edittree->links.first; link; link = link->next) {
-      if (link->tonode == viewer_node && link->fromnode == tonode) {
-        if (link->tosock == viewer_node->inputs.first) {
-          break;
-        }
-      }
+static Vector<const NodeRef *> find_viewer_nodes(const NodeTreeRef &tree)
+{
+  Vector<const NodeRef *> viewer_nodes;
+  for (const NodeRef *node : tree.nodes()) {
+    if (is_viewer_node(*node)) {
+      viewer_nodes.append(node);
     }
-    if (link) {
-      /* unlink existing connection */
-      sock = link->fromsock;
-      nodeRemLink(snode->edittree, link);
+  }
+  return viewer_nodes;
+}
 
-      /* find a socket after the previously connected socket */
-      if (ED_node_is_geometry(snode)) {
-        /* Geometry nodes viewer only supports geometry sockets for now. */
-        for (sock = sock->next; sock; sock = sock->next) {
-          if (sock->type == SOCK_GEOMETRY && !nodeSocketIsHidden(sock)) {
-            break;
-          }
-        }
-      }
-      else {
-        for (sock = sock->next; sock; sock = sock->next) {
-          if (!nodeSocketIsHidden(sock)) {
-            break;
-          }
-        }
-      }
+static bool is_viewer_socket_in_viewer(const InputSocketRef &socket)
+{
+  const NodeRef &node = socket.node();
+  BLI_assert(is_viewer_node(node));
+  if (node.typeinfo()->type == GEO_NODE_VIEWER) {
+    return true;
+  }
+  return socket.index() == 0;
+}
+
+static bool is_linked_to_viewer(const OutputSocketRef &socket, const NodeRef &viewer_node)
+{
+  for (const InputSocketRef *target_socket : socket.directly_linked_sockets()) {
+    if (&target_socket->node() != &viewer_node) {
+      continue;
+    }
+    if (!target_socket->is_available()) {
+      continue;
+    }
+    if (is_viewer_socket_in_viewer(*target_socket)) {
+      return true;
     }
   }
+  return false;
+}
 
-  if (tonode) {
-    /* Find a selected socket that overrides the socket to connect to */
-    if (ED_node_is_geometry(snode)) {
-      /* Geometry nodes viewer only supports geometry sockets for now. */
-      LISTBASE_FOREACH (bNodeSocket *, sock2, &tonode->outputs) {
-        if (sock2->type == SOCK_GEOMETRY && !nodeSocketIsHidden(sock2) && sock2->flag & SELECT) {
-          sock = sock2;
-          break;
-        }
+static int get_default_viewer_type(const bContext *C)
+{
+  SpaceNode *snode = CTX_wm_space_node(C);
+  return ED_node_is_compositor(snode) ? CMP_NODE_VIEWER : GEO_NODE_VIEWER;
+}
+
+static void remove_links_to_unavailable_viewer_sockets(bNodeTree &btree, bNode &viewer_node)
+{
+  LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &btree.links) {
+    if (link->tonode == &viewer_node) {
+      if (link->tosock->flag & SOCK_UNAVAIL) {
+        nodeRemLink(&btree, link);
       }
     }
-    else {
-      LISTBASE_FOREACH (bNodeSocket *, sock2, &tonode->outputs) {
-        if (!nodeSocketIsHidden(sock2) && sock2->flag & SELECT) {
-          sock = sock2;
-          break;
-        }
-      }
+  }
+}
+
+static const NodeRef *get_existing_viewer(const NodeTreeRef &tree)
+{
+  Vector<const NodeRef *> viewer_nodes = find_viewer_nodes(tree);
+
+  /* Check if there is already an active viewer node that should be used. */
+  for (const NodeRef *viewer_node : viewer_nodes) {
+    if (viewer_node->bnode()->flag & NODE_DO_OUTPUT) {
+      return viewer_node;
     }
   }
 
-  /* find a socket starting from the first socket */
-  if (!sock) {
-    if (ED_node_is_geometry(snode)) {
-      /* Geometry nodes viewer only supports geometry sockets for now. */
-      for (sock = (bNodeSocket *)tonode->outputs.first; sock; sock = sock->next) {
-        if (sock->type == SOCK_GEOMETRY && !nodeSocketIsHidden(sock)) {
-          break;
-        }
+  /* If no active but non-active viewers exist, make one active. */
+  if (!viewer_nodes.is_empty()) {
+    viewer_nodes[0]->bnode()->flag |= NODE_DO_OUTPUT;
+    return viewer_nodes[0];
+  }
+  return nullptr;
+}
+
+static const OutputSocketRef *find_output_socket_to_be_viewed(const NodeRef *active_viewer_node,
+                                                              const NodeRef &node_to_view)
+{
+  const OutputSocketRef *last_socket_linked_to_viewer = nullptr;
+  if (active_viewer_node != nullptr) {
+    for (const OutputSocketRef *output_socket : node_to_view.outputs()) {
+      if (!socket_can_be_viewed(*output_socket)) {
+        continue;
       }
-    }
-    else {
-      for (sock = (bNodeSocket *)tonode->outputs.first; sock; sock = sock->next) {
-        if (!nodeSocketIsHidden(sock)) {
-          break;
-        }
+      if (is_linked_to_viewer(*output_socket, *active_viewer_node)) {
+        last_socket_linked_to_viewer = output_socket;
       }
     }
   }
-
-  if (sock) {
-    /* add a new viewer if none exists yet */
-    if (!viewer_node) {
-      /* XXX location is a quick hack, just place it next to the linked socket */
-  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list