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/bl_operators/node.py62
-rw-r--r--release/scripts/startup/bl_operators/spreadsheet.py13
-rw-r--r--release/scripts/startup/bl_ui/space_spreadsheet.py3
-rw-r--r--release/scripts/startup/nodeitems_builtins.py3
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.cc5
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_spreadsheet.h22
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_node/node_add.cc2
-rw-r--r--source/blender/editors/space_node/node_draw.cc22
-rw-r--r--source/blender/editors/space_node/node_edit.cc18
-rw-r--r--source/blender/editors/space_node/node_intern.h1
-rw-r--r--source/blender/editors/space_node/node_relationships.cc33
-rw-r--r--source/blender/editors/space_node/node_select.cc13
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc44
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_context.cc301
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc2
-rw-r--r--source/blender/makesdna/DNA_node_types.h3
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c6
-rw-r--r--source/blender/makesrna/intern/rna_object.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c28
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc30
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc32
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.hh6
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_viewer.cc31
31 files changed, 484 insertions, 208 deletions
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 3cefaf6929b..2959232fa51 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -306,67 +306,6 @@ class NODE_OT_tree_path_parent(Operator):
return {'FINISHED'}
-class NODE_OT_active_preview_toggle(Operator):
- '''Toggle active preview state of node'''
- bl_idname = "node.active_preview_toggle"
- bl_label = "Toggle Active Preview"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- space = context.space_data
- if space is None:
- return False
- if space.type != 'NODE_EDITOR':
- return False
- if space.edit_tree is None:
- return False
- if space.edit_tree.nodes.active is None:
- return False
- return True
-
- def execute(self, context):
- node_editor = context.space_data
- ntree = node_editor.edit_tree
- active_node = ntree.nodes.active
-
- if active_node.active_preview:
- self._disable_preview(context, active_node)
- else:
- self._enable_preview(context, node_editor, ntree, active_node)
-
- return {'FINISHED'}
-
- @classmethod
- def _enable_preview(cls, context, node_editor, ntree, active_node):
- spreadsheets = cls._find_unpinned_spreadsheets(context)
-
- for spreadsheet in spreadsheets:
- spreadsheet.set_geometry_node_context(node_editor, active_node)
-
- for node in ntree.nodes:
- node.active_preview = False
- active_node.active_preview = True
-
- @classmethod
- def _disable_preview(cls, context, active_node):
- spreadsheets = cls._find_unpinned_spreadsheets(context)
- for spreadsheet in spreadsheets:
- spreadsheet.context_path.clear()
-
- active_node.active_preview = False
-
- @staticmethod
- def _find_unpinned_spreadsheets(context):
- spreadsheets = []
- for window in context.window_manager.windows:
- for area in window.screen.areas:
- space = area.spaces.active
- if space.type == 'SPREADSHEET' and not space.is_pinned:
- spreadsheets.append(space)
- return spreadsheets
-
-
classes = (
NodeSetting,
@@ -375,5 +314,4 @@ classes = (
NODE_OT_add_search,
NODE_OT_collapse_hide_unused_toggle,
NODE_OT_tree_path_parent,
- NODE_OT_active_preview_toggle,
)
diff --git a/release/scripts/startup/bl_operators/spreadsheet.py b/release/scripts/startup/bl_operators/spreadsheet.py
index 5cc83d4eddd..1907a69a3d3 100644
--- a/release/scripts/startup/bl_operators/spreadsheet.py
+++ b/release/scripts/startup/bl_operators/spreadsheet.py
@@ -47,18 +47,7 @@ class SPREADSHEET_OT_toggle_pin(Operator):
def unpin(self, context):
space = context.space_data
space.is_pinned = False
-
- space.context_path.clear()
-
- # Try to find a node with an active preview in any open editor.
- if space.object_eval_state == 'EVALUATED':
- node_editors = self.find_geometry_node_editors(context)
- for node_editor in node_editors:
- ntree = node_editor.edit_tree
- for node in ntree.nodes:
- if node.active_preview:
- space.set_geometry_node_context(node_editor, node)
- return
+ space.context_path.guess()
def find_geometry_node_editors(self, context):
editors = []
diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py
index 178be9ef0b7..ad696f23db4 100644
--- a/release/scripts/startup/bl_ui/space_spreadsheet.py
+++ b/release/scripts/startup/bl_ui/space_spreadsheet.py
@@ -54,6 +54,9 @@ class SPREADSHEET_HT_header(bpy.types.Header):
pin_icon = 'PINNED' if space.is_pinned else 'UNPINNED'
layout.operator("spreadsheet.toggle_pin", text="", icon=pin_icon, emboss=False)
+ if space.object_eval_state == 'VIEWER_NODE' and len(context_path) < 3:
+ layout.label(text="No active viewer node.", icon='INFO')
+
layout.separator_spacer()
row = layout.row(align=True)
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index c85d7a9db04..4a7d34f1b69 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -581,6 +581,9 @@ geometry_node_categories = [
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
]),
+ GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
+ NodeItem("GeometryNodeViewer"),
+ ]),
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
NodeItem("GeometryNodePointsToVolume"),
NodeItem("GeometryNodeVolumeToMesh"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index d740b651780..a3387ab554e 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1444,6 +1444,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER 1064
#define GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT 1065
#define GEO_NODE_CURVE_PRIMITIVE_CIRCLE 1066
+#define GEO_NODE_VIEWER 1067
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 56d8853f0cb..293a1b2f69d 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -3151,8 +3151,8 @@ void ntreeSetOutput(bNodeTree *ntree)
if (ntree->type == NTREE_COMPOSIT) {
/* same type, exception for viewer */
if (tnode->type == node->type ||
- (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
- ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
+ (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) &&
+ ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER))) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
@@ -5097,6 +5097,7 @@ static void registerGeometryNodes()
register_node_type_geo_switch();
register_node_type_geo_transform();
register_node_type_geo_triangulate();
+ register_node_type_geo_viewer();
register_node_type_geo_volume_to_mesh();
}
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 73a1548362c..058d4fa91a3 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -40,6 +40,7 @@ struct bNodeSocketType;
struct bNodeTree;
struct bNodeTreeType;
struct bNodeType;
+struct SpaceNode;
typedef enum {
NODE_TOP = 1,
@@ -114,6 +115,7 @@ bool ED_node_select_check(const ListBase *lb);
void ED_node_select_all(ListBase *lb, int action);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain,
+ struct SpaceNode *snode,
struct bNodeTree *ntree,
struct bNode *node,
bool *r_active_texture_changed);
diff --git a/source/blender/editors/include/ED_spreadsheet.h b/source/blender/editors/include/ED_spreadsheet.h
index 88bc4738c0b..ff77135a51c 100644
--- a/source/blender/editors/include/ED_spreadsheet.h
+++ b/source/blender/editors/include/ED_spreadsheet.h
@@ -21,6 +21,9 @@ struct SpaceSpreadsheet;
struct SpaceNode;
struct ID;
struct bNode;
+struct Main;
+struct bContext;
+struct Object;
#ifdef __cplusplus
extern "C" {
@@ -29,14 +32,25 @@ extern "C" {
struct SpreadsheetContext *ED_spreadsheet_context_new(int type);
void ED_spreadsheet_context_free(struct SpreadsheetContext *context);
void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet);
-void ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet);
uint64_t ED_spreadsheet_context_path_hash(const struct SpaceSpreadsheet *sspreadsheet);
struct ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet);
-void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
- struct SpaceNode *snode,
- struct bNode *node);
+void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet,
+ struct SpaceNode *snode,
+ struct bNode *node);
+void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain,
+ struct SpaceNode *snode,
+ struct bNode *node);
+void ED_spreadsheet_context_path_set_evaluated_object(struct SpaceSpreadsheet *sspreadsheet,
+ struct Object *object);
+
+void ED_spreadsheet_context_path_guess(const struct bContext *C,
+ struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_is_active(const struct bContext *C,
+ struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_exists(struct Main *bmain, struct SpaceSpreadsheet *sspreadsheet);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 97e3cb750c1..f1debcef5a9 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -451,7 +451,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
/* set user as active */
if (user->node) {
- ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL);
+ ED_node_set_active(CTX_data_main(C), NULL, user->ntree, user->node, NULL);
ct->texture = NULL;
/* Not totally sure if we should also change selection? */
diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc
index 6143af8ed70..c167744de01 100644
--- a/source/blender/editors/space_node/node_add.cc
+++ b/source/blender/editors/space_node/node_add.cc
@@ -90,7 +90,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
nodeSetSelected(node, true);
ntreeUpdateTree(bmain, snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node, nullptr);
+ ED_node_set_active(bmain, snode, snode->edittree, node, nullptr);
snode_update(snode, node);
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index c15cc4240a5..8a341da0b5c 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -1405,28 +1405,6 @@ static void node_draw_basis(const bContext *C,
"");
UI_block_emboss_set(node->block, UI_EMBOSS);
}
- if (ntree->type == NTREE_GEOMETRY) {
- /* Active preview toggle. */
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- int icon = (node->flag & NODE_ACTIVE_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON;
- uiBut *but = uiDefIconBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- 0,
- icon,
- iconofs,
- rct->ymax - NODE_DY,
- iconbutw,
- UI_UNIT_Y,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- "Show this node's geometry output in the spreadsheet");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_active_preview_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
node_add_error_message_button(C, *ntree, *node, *rct, iconofs);
diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc
index 56064e92d70..9a6603eb589 100644
--- a/source/blender/editors/space_node/node_edit.cc
+++ b/source/blender/editors/space_node/node_edit.cc
@@ -54,6 +54,7 @@
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_spreadsheet.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -662,7 +663,8 @@ void snode_update(SpaceNode *snode, bNode *node)
}
}
-void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
+void ED_node_set_active(
+ Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
{
const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
if (r_active_texture_changed) {
@@ -782,6 +784,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
}
#endif
}
+ else if (ntree->type == NTREE_GEOMETRY) {
+ if (node->type == GEO_NODE_VIEWER) {
+ if ((node->flag & NODE_DO_OUTPUT) == 0) {
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->type == GEO_NODE_VIEWER) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ node->flag |= NODE_DO_OUTPUT;
+ ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node);
+ }
+ }
+ }
}
}
@@ -1318,7 +1333,6 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
nodeSetSelected(node, false);
node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
nodeSetSelected(newnode, true);
- newnode->flag &= ~NODE_ACTIVE_PREVIEW;
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode));
}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 58c3c8181b2..e69f0cbea7f 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -279,7 +279,6 @@ void NODE_OT_hide_toggle(struct wmOperatorType *ot);
void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot);
void NODE_OT_preview_toggle(struct wmOperatorType *ot);
void NODE_OT_options_toggle(struct wmOperatorType *ot);
-void NODE_OT_active_preview_toggle(struct wmOperatorType *ot);
void NODE_OT_node_copy_color(struct wmOperatorType *ot);
void NODE_OT_read_viewlayers(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index a1b8e4e3395..aadf93961e9 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -40,11 +40,14 @@
#include "ED_node.h" /* own include */
#include "ED_render.h"
#include "ED_screen.h"
+#include "ED_spreadsheet.h"
#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -160,6 +163,11 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node)
return true;
}
}
+ if (current_node->type == GEO_NODE_VIEWER) {
+ if (ntree_check_nodes_connected(ntree, node, current_node)) {
+ return true;
+ }
+ }
}
return false;
}
@@ -610,14 +618,14 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (tonode == nullptr || BLI_listbase_is_empty(&tonode->outputs)) {
return OPERATOR_CANCELLED;
}
- if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
return OPERATOR_CANCELLED;
}
/* get viewer */
bNode *viewer_node = nullptr;
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
if (node->flag & NODE_DO_OUTPUT) {
viewer_node = node;
break;
@@ -627,7 +635,7 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* 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)) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
node->flag |= NODE_DO_OUTPUT;
viewer_node = node;
break;
@@ -686,7 +694,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* 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 */
- viewer_node = node_add_node(C, nullptr, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
+ const int viewer_type = ED_node_is_compositor(snode) ? CMP_NODE_VIEWER : GEO_NODE_VIEWER;
+ viewer_node = node_add_node(C, nullptr, viewer_type, sock->locx + 100, sock->locy);
if (!viewer_node) {
return OPERATOR_CANCELLED;
}
@@ -712,8 +721,13 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* make sure the dependency sorting is updated */
snode->edittree->update |= NTREE_UPDATE_LINKS;
}
+ if (ED_node_is_geometry(snode)) {
+ ED_spreadsheet_context_paths_set_geometry_node(CTX_data_main(C), snode, viewer_node);
+ }
+
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_update(snode, viewer_node);
+ DEG_id_tag_update(&snode->edittree->id, 0);
}
return OPERATOR_FINISHED;
@@ -739,6 +753,15 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static bool node_active_link_viewer_poll(bContext *C)
+{
+ if (!ED_operator_node_editable(C)) {
+ return false;
+ }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ return ED_node_is_compositor(snode) || ED_node_is_geometry(snode);
+}
+
void NODE_OT_link_viewer(wmOperatorType *ot)
{
/* identifiers */
@@ -748,7 +771,7 @@ void NODE_OT_link_viewer(wmOperatorType *ot)
/* api callbacks */
ot->exec = node_active_link_viewer_exec;
- ot->poll = composite_node_editable;
+ ot->poll = node_active_link_viewer_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index 2c8e78de8d2..a081cc83481 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -44,6 +44,7 @@
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_spreadsheet.h"
#include "ED_view3d.h"
#include "RNA_access.h"
@@ -469,7 +470,7 @@ void node_select_single(bContext *C, bNode *node)
}
nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
+ ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed);
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
@@ -606,12 +607,18 @@ static int node_mouse_select(bContext *C,
/* update node order */
if (ret_value != OPERATOR_CANCELLED) {
bool active_texture_changed = false;
+ bool viewer_node_changed = false;
if (node != nullptr && ret_value != OPERATOR_RUNNING_MODAL) {
- ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
+ viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER;
+ ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed);
+ }
+ else if (node != nullptr && node->type == GEO_NODE_VIEWER) {
+ ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node);
}
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
- if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) {
+ if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) ||
+ viewer_node_changed) {
DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
}
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 07517f9e60f..fcc92345bea 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -222,24 +222,11 @@ ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet)
static void update_pinned_context_path_if_outdated(const bContext *C)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
-
- /* Currently, this only checks if the object has been deleted. In the future we can have a more
- * sophisticated check for the entire context (including modifier and nodes). */
- LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
- if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
- SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context;
- if (object_context->object == nullptr) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- break;
- }
- }
- }
- if (BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- Object *active_object = CTX_data_active_object(C);
- if (active_object != nullptr) {
- SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT);
- ((SpreadsheetContextObject *)new_context)->object = active_object;
- BLI_addtail(&sspreadsheet->context_path, new_context);
+ Main *bmain = CTX_data_main(C);
+ if (!ED_spreadsheet_context_path_exists(bmain, sspreadsheet)) {
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
+ if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
}
}
@@ -252,25 +239,12 @@ static void update_pinned_context_path_if_outdated(const bContext *C)
static void update_context_path_from_context(const bContext *C)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
- Object *active_object = CTX_data_active_object(C);
- if (active_object == nullptr) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- return;
- }
- if (!BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first;
- if (root_context->type == SPREADSHEET_CONTEXT_OBJECT) {
- SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context;
- if (object_context->object != active_object) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- }
+ if (!ED_spreadsheet_context_path_is_active(C, sspreadsheet)) {
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
+ if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
}
}
- if (BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT);
- ((SpreadsheetContextObject *)new_context)->object = active_object;
- BLI_addtail(&sspreadsheet->context_path, new_context);
- }
}
void spreadsheet_update_context_path(const bContext *C)
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
index af6ab5d1b92..93d7c6d9804 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
@@ -24,16 +24,28 @@
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
+#include "ED_screen.h"
#include "ED_spreadsheet.h"
#include "DEG_depsgraph.h"
+#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_workspace.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_windowmanager_types.h"
#include "spreadsheet_context.hh"
+using blender::IndexRange;
+using blender::Span;
+using blender::StringRef;
+using blender::Vector;
+
namespace blender::ed::spreadsheet {
static SpreadsheetContextObject *spreadsheet_context_object_new()
@@ -206,28 +218,30 @@ void spreadsheet_context_free(SpreadsheetContext *context)
/**
* Tag any data relevant to the spreadsheet's context for recalculation in order to collect
* information to display in the editor, which may be cached during evaluation.
+ * \return True when any data has been tagged for update.
*/
-static void spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet)
+static bool spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet)
{
using namespace blender;
Vector<const SpreadsheetContext *> context_path = sspreadsheet->context_path;
if (context_path.is_empty()) {
- return;
+ return false;
}
if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
- return;
+ return false;
}
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0];
Object *object = object_context->object;
if (object == nullptr) {
- return;
+ return false;
}
if (context_path.size() == 1) {
/* No need to reevaluate, when the final or original object is viewed. */
- return;
+ return false;
}
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ return true;
}
} // namespace blender::ed::spreadsheet
@@ -250,9 +264,9 @@ void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet)
BLI_listbase_clear(&sspreadsheet->context_path);
}
-void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
+bool ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
{
- blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
+ return blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
}
uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet)
@@ -265,15 +279,32 @@ uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet)
return BLI_hash_mm2a_end(&mm2);
}
-void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
- struct SpaceNode *snode,
- struct bNode *node)
+void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet,
+ struct SpaceNode *snode,
+ struct bNode *node)
{
using namespace blender::ed::spreadsheet;
- ED_spreadsheet_context_path_clear(sspreadsheet);
Object *object = (Object *)snode->id;
+ /* Try to find the modifier the node tree belongs to. */
ModifierData *modifier = BKE_object_active_modifier(object);
+ if (modifier && modifier->type != eModifierType_Nodes) {
+ modifier = nullptr;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->type == eModifierType_Nodes) {
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ if (nmd->node_group == snode->nodetree) {
+ modifier = md;
+ break;
+ }
+ }
+ }
+ }
+ if (modifier == nullptr) {
+ return;
+ }
+
+ ED_spreadsheet_context_path_clear(sspreadsheet);
{
SpreadsheetContextObject *context = spreadsheet_context_object_new();
@@ -302,5 +333,251 @@ void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsh
BLI_addtail(&sspreadsheet->context_path, context);
}
- sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED;
+ sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE;
+}
+
+void ED_spreadsheet_context_paths_set_geometry_node(Main *bmain, SpaceNode *snode, bNode *node)
+{
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return;
+ }
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype == SPACE_SPREADSHEET) {
+ SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
+ if ((sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) == 0) {
+ const uint64_t context_hash_before = ED_spreadsheet_context_path_hash(sspreadsheet);
+ ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node);
+ const uint64_t context_hash_after = ED_spreadsheet_context_path_hash(sspreadsheet);
+ if (context_hash_before != context_hash_after) {
+ ED_spreadsheet_context_path_update_tag(sspreadsheet);
+ }
+ ED_area_tag_redraw(area);
+ }
+ }
+ }
+ }
+}
+
+void ED_spreadsheet_context_path_set_evaluated_object(SpaceSpreadsheet *sspreadsheet,
+ Object *object)
+{
+ using namespace blender::ed::spreadsheet;
+ ED_spreadsheet_context_path_clear(sspreadsheet);
+
+ SpreadsheetContextObject *context = spreadsheet_context_object_new();
+ context->object = object;
+ BLI_addtail(&sspreadsheet->context_path, context);
+}
+
+void ED_spreadsheet_context_path_guess(const bContext *C, SpaceSpreadsheet *sspreadsheet)
+{
+ ED_spreadsheet_context_path_clear(sspreadsheet);
+
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return;
+ }
+
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ if (snode->edittree != nullptr) {
+ if (snode->edittree->type == NTREE_GEOMETRY) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
+ if (node->type == GEO_NODE_VIEWER) {
+ if (node->flag & NODE_DO_OUTPUT) {
+ ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Object *active_object = CTX_data_active_object(C);
+ if (active_object != nullptr) {
+ ED_spreadsheet_context_path_set_evaluated_object(sspreadsheet, active_object);
+ return;
+ }
+}
+
+bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *sspreadsheet)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return false;
+ }
+ Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path;
+ if (context_path.is_empty()) {
+ return false;
+ }
+ if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
+ return false;
+ }
+ Object *object = ((SpreadsheetContextObject *)context_path[0])->object;
+ if (object == nullptr) {
+ return false;
+ }
+ if (context_path.size() == 1) {
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ return false;
+ }
+ Object *active_object = CTX_data_active_object(C);
+ return object == active_object;
+ }
+ if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ return false;
+ }
+ if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
+ return false;
+ }
+ const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name;
+ const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name);
+ if (modifier == nullptr) {
+ return false;
+ }
+ if (!(modifier->flag & eModifierFlag_Active)) {
+ return false;
+ }
+ if (modifier->type != eModifierType_Nodes) {
+ return false;
+ }
+ bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group;
+ if (root_node_tree == nullptr) {
+ return false;
+ }
+ const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2);
+ if (node_context_path.is_empty()) {
+ return false;
+ }
+
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype != SPACE_NODE) {
+ continue;
+ }
+ SpaceNode *snode = (SpaceNode *)sl;
+ if (snode->nodetree != root_node_tree) {
+ continue;
+ }
+ if (snode->id != &object->id) {
+ continue;
+ }
+ Vector<bNodeTreePath *> tree_path = snode->treepath;
+ if (node_context_path.size() != tree_path.size()) {
+ continue;
+ }
+ int valid_count = 0;
+ for (const int i : IndexRange(tree_path.size() - 1)) {
+ if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) {
+ break;
+ }
+ SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)node_context_path[i];
+ if (!STREQ(node_context->node_name, tree_path[i]->node_name)) {
+ break;
+ }
+ valid_count++;
+ }
+ if (valid_count != tree_path.size() - 1) {
+ continue;
+ }
+ SpreadsheetContext *last_context = node_context_path.last();
+ if (last_context->type != SPREADSHEET_CONTEXT_NODE) {
+ return false;
+ }
+ const char *node_name = ((SpreadsheetContextNode *)last_context)->node_name;
+ bNode *node = nodeFindNodebyName(snode->edittree, node_name);
+ if (node == nullptr) {
+ return false;
+ }
+ if (node->type != GEO_NODE_VIEWER) {
+ return false;
+ }
+ if (!(node->flag & NODE_DO_OUTPUT)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ED_spreadsheet_context_path_exists(Main *UNUSED(bmain), SpaceSpreadsheet *sspreadsheet)
+{
+ Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path;
+ if (context_path.is_empty()) {
+ return false;
+ }
+ if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
+ return false;
+ }
+ Object *object = ((SpreadsheetContextObject *)context_path[0])->object;
+ if (object == nullptr) {
+ return false;
+ }
+ if (context_path.size() == 1) {
+ return true;
+ }
+ if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
+ return false;
+ }
+ const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name;
+ const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name);
+ if (modifier == nullptr) {
+ return false;
+ }
+ if (modifier->type != eModifierType_Nodes) {
+ return false;
+ }
+ bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group;
+ if (root_node_tree == nullptr) {
+ return false;
+ }
+ const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2);
+ if (node_context_path.is_empty()) {
+ return false;
+ }
+ bNodeTree *node_tree = root_node_tree;
+ for (const int i : node_context_path.index_range()) {
+ if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) {
+ return false;
+ }
+ const char *node_name = ((SpreadsheetContextNode *)node_context_path[i])->node_name;
+ bNode *node = nodeFindNodebyName(node_tree, node_name);
+ if (node == nullptr) {
+ return false;
+ }
+ if (node->type == GEO_NODE_VIEWER) {
+ if (i == node_context_path.index_range().last()) {
+ return true;
+ }
+ return false;
+ }
+ else if (node->id != nullptr) {
+ if (GS(node->id->name) != ID_NT) {
+ return false;
+ }
+ node_tree = (bNodeTree *)node->id;
+ }
+ else {
+ return false;
+ }
+ }
+ return false;
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index 6d244a1bda6..f730f199ca4 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -419,7 +419,7 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
}
}
- else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED) {
+ else {
if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
if (mesh == nullptr) {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 6b9ef6a2e54..54bd792294f 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -325,6 +325,7 @@ typedef struct bNode {
#define NODE_HIDDEN 8
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
+/* Used to indicate which group output node is used and which viewer node is active. */
#define NODE_DO_OUTPUT 64
#define __NODE_GROUP_EDIT 128 /* DEPRECATED */
/* free test flag, undefined */
@@ -359,7 +360,7 @@ typedef struct bNode {
*/
#define NODE_DO_OUTPUT_RECALC (1 << 17)
/* A preview for the data in this node can be displayed in the spreadsheet editor. */
-#define NODE_ACTIVE_PREVIEW (1 << 18)
+#define __NODE_ACTIVE_PREVIEW (1 << 18) /* deprecated */
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index bf5d820056b..557343f79cd 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1922,6 +1922,7 @@ typedef enum eSpreadsheetFilterOperation {
typedef enum eSpaceSpreadsheet_ObjectEvalState {
SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED = 0,
SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
+ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE = 2,
} eSpaceSpreadsheet_Context;
typedef enum eSpaceSpreadsheet_ContextType {
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 73f26f87a74..7def9bdb636 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -690,6 +690,7 @@ static void rna_Modifier_is_active_set(PointerRNA *ptr, bool value)
}
md->flag |= eModifierFlag_Active;
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id);
}
}
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 50e8f78df8f..d9e199e5eb2 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -11320,12 +11320,6 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Texture", "Display node in viewport textured shading mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
- prop = RNA_def_property(srna, "active_preview", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_PREVIEW);
- RNA_def_property_ui_text(prop, "Active Preview", "Node is previewed in other editor");
- RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
- RNA_def_property_update(prop, NC_NODE, NULL);
-
/* generic property update function */
func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update");
RNA_def_function_ui_description(func, "Update after property changes");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 86a679550f4..7c012922c2c 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1706,6 +1706,8 @@ static void rna_Object_active_modifier_set(PointerRNA *ptr, PointerRNA value, Re
Object *ob = (Object *)ptr->owner_id;
ModifierData *md = value.data;
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+
if (RNA_pointer_is_null(&value)) {
BKE_object_modifier_set_active(ob, NULL);
return;
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 8b2927019dd..c05842d3cfe 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3177,11 +3177,9 @@ static void rna_spreadsheet_context_update(Main *UNUSED(bmain),
}
}
-static void rna_spreadsheet_set_geometry_node_context(SpaceSpreadsheet *sspreadsheet,
- SpaceNode *snode,
- bNode *node)
+static void rna_SpaceSpreadsheet_context_path_guess(SpaceSpreadsheet *sspreadsheet, bContext *C)
{
- ED_spreadsheet_set_geometry_node_context(sspreadsheet, snode, node);
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
ED_spreadsheet_context_path_update_tag(sspreadsheet);
WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
}
@@ -7646,13 +7644,16 @@ static void rna_def_space_spreadsheet_context_path(BlenderRNA *brna, PropertyRNA
func = RNA_def_function(srna, "clear", "rna_SpaceSpreadsheet_context_path_clear");
RNA_def_function_ui_description(func, "Clear entire context path");
+
+ func = RNA_def_function(srna, "guess", "rna_SpaceSpreadsheet_context_path_guess");
+ RNA_def_function_ui_description(func, "Guess the context path from the current context");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
}
static void rna_def_space_spreadsheet(BlenderRNA *brna)
{
- PropertyRNA *prop, *parm;
+ PropertyRNA *prop;
StructRNA *srna;
- FunctionRNA *func;
static const EnumPropertyItem geometry_component_type_items[] = {
{GEO_COMPONENT_TYPE_MESH,
@@ -7689,6 +7690,11 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
ICON_NONE,
"Original",
"Use data from original object without any modifiers applied"},
+ {SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE,
+ "VIEWER_NODE",
+ ICON_NONE,
+ "Viewer Node",
+ "Use intermediate data from viewer node"},
{0, NULL, 0, NULL, NULL},
};
@@ -7764,16 +7770,6 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SpreadsheetRowFilter");
RNA_def_property_ui_text(prop, "Row Filters", "Filters to remove rows from the displayed data");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
-
- func = RNA_def_function(
- srna, "set_geometry_node_context", "rna_spreadsheet_set_geometry_node_context");
- RNA_def_function_ui_description(
- func, "Update context_path to point to a specific node in a node editor");
- parm = RNA_def_pointer(
- func, "node_editor", "SpaceNodeEditor", "", "Editor to take the context from");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "node", "Node", "", "");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
void RNA_def_space(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index f7f7c7b0276..76eec76acb4 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -768,22 +768,6 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain)
using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>;
-static DSocket try_find_preview_socket_in_node(const DNode node)
-{
- for (const SocketRef *socket : node->outputs()) {
- if (socket->bsocket()->type == SOCK_GEOMETRY) {
- return {node.context(), socket};
- }
- }
- for (const SocketRef *socket : node->inputs()) {
- if (socket->bsocket()->type == SOCK_GEOMETRY &&
- (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) {
- return {node.context(), socket};
- }
- }
- return {};
-}
-
static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet,
NodesModifierData *nmd,
const ModifierEvalContext *ctx,
@@ -839,7 +823,17 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre
const NodeTreeRef &tree_ref = context->tree();
for (const NodeRef *node_ref : tree_ref.nodes()) {
if (node_ref->name() == last_context->node_name) {
- return try_find_preview_socket_in_node({context, node_ref});
+ const DNode viewer_node{context, node_ref};
+ DSocket socket_to_view;
+ viewer_node.input(0).foreach_origin_socket(
+ [&](const DSocket socket) { socket_to_view = socket; });
+ if (!socket_to_view) {
+ return {};
+ }
+ bNodeSocket *bsocket = socket_to_view->bsocket();
+ if (bsocket->type == SOCK_GEOMETRY && bsocket->flag != SOCK_MULTI_INPUT) {
+ return socket_to_view;
+ }
}
}
return {};
@@ -975,6 +969,8 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params;
eval_params.input_values = group_inputs;
eval_params.output_sockets = group_outputs;
+ eval_params.force_compute_sockets.extend(preview_sockets.keys().begin(),
+ preview_sockets.keys().end());
eval_params.mf_by_node = &mf_by_node;
eval_params.modifier_ = nmd;
eval_params.depsgraph = ctx->depsgraph;
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 8314a443ba6..205bfa34465 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -404,6 +404,9 @@ class GeometryNodesEvaluator {
for (const DInputSocket &socket : params_.output_sockets) {
nodes_to_check.push(socket.node());
}
+ for (const DSocket &socket : params_.force_compute_sockets) {
+ nodes_to_check.push(socket.node());
+ }
/* Use the local allocator because the states do not need to outlive the evaluator. */
LinearAllocator<> &allocator = local_allocators_.local();
while (!nodes_to_check.is_empty()) {
@@ -501,7 +504,8 @@ class GeometryNodesEvaluator {
},
{});
if (output_state.potential_users == 0) {
- /* If it does not have any potential users, it is unused. */
+ /* If it does not have any potential users, it is unused. It might become required again in
+ * `schedule_initial_nodes`. */
output_state.output_usage = ValueUsage::Unused;
}
}
@@ -576,6 +580,20 @@ class GeometryNodesEvaluator {
this->set_input_required(locked_node, socket);
});
}
+ for (const DSocket socket : params_.force_compute_sockets) {
+ const DNode node = socket.node();
+ NodeState &node_state = this->get_node_state(node);
+ this->with_locked_node(node, node_state, [&](LockedNode &locked_node) {
+ if (socket->is_input()) {
+ this->set_input_required(locked_node, DInputSocket(socket));
+ }
+ else {
+ OutputState &output_state = node_state.outputs[socket->index()];
+ output_state.output_usage = ValueUsage::Required;
+ this->schedule_node(locked_node);
+ }
+ });
+ }
}
void schedule_node(LockedNode &locked_node)
@@ -1124,10 +1142,14 @@ class GeometryNodesEvaluator {
this->with_locked_node(node, node_state, [&](LockedNode &locked_node) {
output_state.potential_users -= 1;
if (output_state.potential_users == 0) {
- /* The output socket has no users anymore. */
- output_state.output_usage = ValueUsage::Unused;
- /* Schedule the origin node in case it wants to set its inputs as unused as well. */
- this->schedule_node(locked_node);
+ /* The socket might be required even though the output is not used by other sockets. That
+ * can happen when the socket is forced to be computed. */
+ if (output_state.output_usage != ValueUsage::Required) {
+ /* The output socket has no users anymore. */
+ output_state.output_usage = ValueUsage::Unused;
+ /* Schedule the origin node in case it wants to set its inputs as unused as well. */
+ this->schedule_node(locked_node);
+ }
}
});
}
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
index 84249e4244e..58eb6a4cd0b 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
@@ -38,6 +38,12 @@ struct GeometryNodesEvaluationParams {
Map<DOutputSocket, GMutablePointer> input_values;
Vector<DInputSocket> output_sockets;
+ /* These sockets will be computed but are not part of the output. Their value can be retrieved in
+ * `log_socket_value_fn`. These sockets are not part of `output_sockets` because then the
+ * evaluator would have to keep the socket values in memory until the end, which might not be
+ * necessary in all cases. Sometimes `log_socket_value_fn` might just want to look at the value
+ * and then it can be freed. */
+ Vector<DSocket> force_compute_sockets;
nodes::MultiFunctionByNode *mf_by_node;
const NodesModifierData *modifier_;
Depsgraph *depsgraph;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 77d2f043b64..49e40060c0f 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -206,6 +206,7 @@ set(SRC
geometry/nodes/node_geo_switch.cc
geometry/nodes/node_geo_transform.cc
geometry/nodes/node_geo_triangulate.cc
+ geometry/nodes/node_geo_viewer.cc
geometry/nodes/node_geo_volume_to_mesh.cc
geometry/node_geometry_exec.cc
geometry/node_geometry_tree.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 3e41c37ca75..5422eb6a5bf 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -95,6 +95,7 @@ void register_node_type_geo_subdivision_surface(void);
void register_node_type_geo_switch(void);
void register_node_type_geo_transform(void);
void register_node_type_geo_triangulate(void);
+void register_node_type_geo_viewer(void);
void register_node_type_geo_volume_to_mesh(void);
#ifdef __cplusplus
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index f6063039bfc..1d906033128 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -333,6 +333,7 @@ DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", Su
DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "")
DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "")
DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "")
+DefNode(GeometryNode, GEO_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "")
DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "")
/* undefine macros */
diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
new file mode 100644
index 00000000000..f0b91f49f52
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
@@ -0,0 +1,31 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_viewer_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+void register_node_type_geo_viewer()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, 0);
+ node_type_socket_templates(&ntype, geo_node_viewer_in, nullptr);
+ nodeRegisterType(&ntype);
+}