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:
authorJacques Lucke <jacques@blender.org>2022-09-13 09:44:26 +0300
committerJacques Lucke <jacques@blender.org>2022-09-13 09:44:32 +0300
commit4130f1e674f83fc3d53979d3061469af34e1f873 (patch)
treedb0da10f143d39b0198d2def4e39bd8df9d1656e /source/blender/editors
parent4d69b6f525a4f02a24141e61f16e90455f3f0a30 (diff)
Geometry Nodes: new evaluation system
This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/UI_interface.hh13
-rw-r--r--source/blender/editors/interface/interface_template_attribute_search.cc6
-rw-r--r--source/blender/editors/space_node/node_draw.cc451
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc65
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc49
5 files changed, 287 insertions, 297 deletions
diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh
index 82bfdd7e212..6c756984203 100644
--- a/source/blender/editors/include/UI_interface.hh
+++ b/source/blender/editors/include/UI_interface.hh
@@ -13,7 +13,7 @@
#include "UI_resources.h"
-namespace blender::nodes::geometry_nodes_eval_log {
+namespace blender::nodes::geo_eval_log {
struct GeometryAttributeInfo;
}
@@ -44,12 +44,11 @@ void context_path_add_generic(Vector<ContextPathItem> &path,
void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path);
-void attribute_search_add_items(
- StringRefNull str,
- bool can_create_attribute,
- Span<const nodes::geometry_nodes_eval_log::GeometryAttributeInfo *> infos,
- uiSearchItems *items,
- bool is_first);
+void attribute_search_add_items(StringRefNull str,
+ bool can_create_attribute,
+ Span<const nodes::geo_eval_log::GeometryAttributeInfo *> infos,
+ uiSearchItems *items,
+ bool is_first);
} // namespace blender::ui
diff --git a/source/blender/editors/interface/interface_template_attribute_search.cc b/source/blender/editors/interface/interface_template_attribute_search.cc
index 0a684903f0f..55ca945671f 100644
--- a/source/blender/editors/interface/interface_template_attribute_search.cc
+++ b/source/blender/editors/interface/interface_template_attribute_search.cc
@@ -14,13 +14,15 @@
#include "BLT_translation.h"
-#include "NOD_geometry_nodes_eval_log.hh"
+#include "BKE_attribute.hh"
+
+#include "NOD_geometry_nodes_log.hh"
#include "UI_interface.h"
#include "UI_interface.hh"
#include "UI_resources.h"
-using blender::nodes::geometry_nodes_eval_log::GeometryAttributeInfo;
+using blender::nodes::geo_eval_log::GeometryAttributeInfo;
namespace blender::ui {
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 3da799d0fd5..3a8e5d0aed6 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -13,6 +13,7 @@
#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -29,11 +30,13 @@
#include "BLT_translation.h"
+#include "BKE_compute_contexts.hh"
#include "BKE_context.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_node_runtime.hh"
#include "BKE_node_tree_update.h"
#include "BKE_object.h"
@@ -65,7 +68,8 @@
#include "RNA_access.h"
#include "RNA_prototypes.h"
-#include "NOD_geometry_nodes_eval_log.hh"
+#include "NOD_geometry_exec.hh"
+#include "NOD_geometry_nodes_log.hh"
#include "NOD_node_declaration.hh"
#include "NOD_socket_declarations_geometry.hh"
@@ -74,10 +78,11 @@
#include "node_intern.hh" /* own include */
+namespace geo_log = blender::nodes::geo_eval_log;
+
using blender::GPointer;
+using blender::Vector;
using blender::fn::GField;
-namespace geo_log = blender::nodes::geometry_nodes_eval_log;
-using geo_log::eNamedAttrUsage;
extern "C" {
/* XXX interface.h */
@@ -85,6 +90,17 @@ extern void ui_draw_dropshadow(
const rctf *rct, float radius, float aspect, float alpha, int select);
}
+/**
+ * This is passed to many functions which draw the node editor.
+ */
+struct TreeDrawContext {
+ /**
+ * Geometry nodes logs various data during execution. The logged data that corresponds to the
+ * currently drawn node tree can be retrieved from the log below.
+ */
+ geo_log::GeoTreeLog *geo_tree_log = nullptr;
+};
+
float ED_node_grid_size()
{
return U.widget_unit;
@@ -157,6 +173,12 @@ void ED_node_tag_update_id(ID *id)
namespace blender::ed::space_node {
+static void node_socket_add_tooltip_in_node_editor(TreeDrawContext * /*tree_draw_ctx*/,
+ const bNodeTree *ntree,
+ const bNode *node,
+ const bNodeSocket *sock,
+ uiLayout *layout);
+
static bool compare_nodes(const bNode *a, const bNode *b)
{
/* These tell if either the node or any of the parent nodes is selected.
@@ -313,7 +335,11 @@ float2 node_from_view(const bNode &node, const float2 &co)
/**
* Based on settings and sockets in node, set drawing rect info.
*/
-static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, uiBlock &block)
+static void node_update_basis(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
+ bNodeTree &ntree,
+ bNode &node,
+ uiBlock &block)
{
PointerRNA nodeptr;
RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr);
@@ -374,7 +400,7 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node,
const char *socket_label = nodeSocketLabel(socket);
socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label));
- node_socket_add_tooltip(ntree, node, *socket, *row);
+ node_socket_add_tooltip_in_node_editor(&tree_draw_ctx, &ntree, &node, socket, row);
UI_block_align_end(&block);
UI_block_layout_resolve(&block, nullptr, &buty);
@@ -506,7 +532,7 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node,
const char *socket_label = nodeSocketLabel(socket);
socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label));
- node_socket_add_tooltip(ntree, node, *socket, *row);
+ node_socket_add_tooltip_in_node_editor(&tree_draw_ctx, &ntree, &node, socket, row);
UI_block_align_end(&block);
UI_block_layout_resolve(&block, nullptr, &buty);
@@ -823,25 +849,16 @@ static void create_inspection_string_for_generic_value(const GPointer value, std
}
}
-static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &value_log,
- std::stringstream &ss)
+static void create_inspection_string_for_field_info(const geo_log::FieldInfoLog &value_log,
+ std::stringstream &ss)
{
- const CPPType &type = value_log.type();
- const GField &field = value_log.field();
- const Span<std::string> input_tooltips = value_log.input_tooltips();
+ const CPPType &type = value_log.type;
+ const Span<std::string> input_tooltips = value_log.input_tooltips;
if (input_tooltips.is_empty()) {
- if (field) {
- BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
- blender::fn::evaluate_constant_field(field, buffer);
- create_inspection_string_for_generic_value({type, buffer}, ss);
- type.destruct(buffer);
- }
- else {
- /* Constant values should always be logged. */
- BLI_assert_unreachable();
- ss << "Value has not been logged";
- }
+ /* Should have been logged as constant value. */
+ BLI_assert_unreachable();
+ ss << "Value has not been logged";
}
else {
if (type.is<int>()) {
@@ -874,11 +891,11 @@ static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &v
}
}
-static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log,
- std::stringstream &ss,
- const nodes::decl::Geometry *geometry)
+static void create_inspection_string_for_geometry_info(const geo_log::GeometryInfoLog &value_log,
+ std::stringstream &ss,
+ const nodes::decl::Geometry *socket_decl)
{
- Span<GeometryComponentType> component_types = value_log.component_types();
+ Span<GeometryComponentType> component_types = value_log.component_types;
if (component_types.is_empty()) {
ss << TIP_("Empty Geometry");
return;
@@ -895,7 +912,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
const char *line_end = (type == component_types.last()) ? "" : ".\n";
switch (type) {
case GEO_COMPONENT_TYPE_MESH: {
- const geo_log::GeometryValueLog::MeshInfo &mesh_info = *value_log.mesh_info;
+ const geo_log::GeometryInfoLog::MeshInfo &mesh_info = *value_log.mesh_info;
char line[256];
BLI_snprintf(line,
sizeof(line),
@@ -907,7 +924,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
break;
}
case GEO_COMPONENT_TYPE_POINT_CLOUD: {
- const geo_log::GeometryValueLog::PointCloudInfo &pointcloud_info =
+ const geo_log::GeometryInfoLog::PointCloudInfo &pointcloud_info =
*value_log.pointcloud_info;
char line[256];
BLI_snprintf(line,
@@ -918,7 +935,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
break;
}
case GEO_COMPONENT_TYPE_CURVE: {
- const geo_log::GeometryValueLog::CurveInfo &curve_info = *value_log.curve_info;
+ const geo_log::GeometryInfoLog::CurveInfo &curve_info = *value_log.curve_info;
char line[256];
BLI_snprintf(line,
sizeof(line),
@@ -928,7 +945,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
break;
}
case GEO_COMPONENT_TYPE_INSTANCES: {
- const geo_log::GeometryValueLog::InstancesInfo &instances_info = *value_log.instances_info;
+ const geo_log::GeometryInfoLog::InstancesInfo &instances_info = *value_log.instances_info;
char line[256];
BLI_snprintf(line,
sizeof(line),
@@ -943,7 +960,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
}
case GEO_COMPONENT_TYPE_EDIT: {
if (value_log.edit_data_info.has_value()) {
- const geo_log::GeometryValueLog::EditDataInfo &edit_info = *value_log.edit_data_info;
+ const geo_log::GeometryInfoLog::EditDataInfo &edit_info = *value_log.edit_data_info;
char line[256];
BLI_snprintf(line,
sizeof(line),
@@ -959,11 +976,11 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
/* If the geometry declaration is null, as is the case for input to group output,
* or it is an output socket don't show supported types. */
- if (geometry == nullptr || geometry->in_out() == SOCK_OUT) {
+ if (socket_decl == nullptr || socket_decl->in_out() == SOCK_OUT) {
return;
}
- Span<GeometryComponentType> supported_types = geometry->supported_types();
+ Span<GeometryComponentType> supported_types = socket_decl->supported_types();
if (supported_types.is_empty()) {
ss << ".\n\n" << TIP_("Supported: All Types");
return;
@@ -1000,43 +1017,37 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo
}
}
-static std::optional<std::string> create_socket_inspection_string(const bContext &C,
- const bNode &node,
+static std::optional<std::string> create_socket_inspection_string(TreeDrawContext &tree_draw_ctx,
const bNodeSocket &socket)
{
- const SpaceNode *snode = CTX_wm_space_node(&C);
- if (snode == nullptr) {
- return {};
- };
-
- const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context(
- *snode, node, socket);
- if (socket_log == nullptr) {
- return {};
- }
- const geo_log::ValueLog *value_log = socket_log->value();
+ using namespace blender::nodes::geo_eval_log;
+ tree_draw_ctx.geo_tree_log->ensure_socket_values();
+ ValueLog *value_log = tree_draw_ctx.geo_tree_log->find_socket_value_log(socket);
if (value_log == nullptr) {
- return {};
+ return std::nullopt;
}
-
std::stringstream ss;
if (const geo_log::GenericValueLog *generic_value_log =
dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
- create_inspection_string_for_generic_value(generic_value_log->value(), ss);
+ create_inspection_string_for_generic_value(generic_value_log->value, ss);
}
- if (const geo_log::GFieldValueLog *gfield_value_log =
- dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) {
- create_inspection_string_for_gfield(*gfield_value_log, ss);
+ else if (const geo_log::FieldInfoLog *gfield_value_log =
+ dynamic_cast<const geo_log::FieldInfoLog *>(value_log)) {
+ create_inspection_string_for_field_info(*gfield_value_log, ss);
}
- else if (const geo_log::GeometryValueLog *geo_value_log =
- dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
- create_inspection_string_for_geometry(
+ else if (const geo_log::GeometryInfoLog *geo_value_log =
+ dynamic_cast<const geo_log::GeometryInfoLog *>(value_log)) {
+ create_inspection_string_for_geometry_info(
*geo_value_log,
ss,
dynamic_cast<const nodes::decl::Geometry *>(socket.runtime->declaration));
}
- return ss.str();
+ std::string str = ss.str();
+ if (str.empty()) {
+ return std::nullopt;
+ }
+ return str;
}
static bool node_socket_has_tooltip(const bNodeTree &ntree, const bNodeSocket &socket)
@@ -1046,34 +1057,42 @@ static bool node_socket_has_tooltip(const bNodeTree &ntree, const bNodeSocket &s
}
if (socket.runtime->declaration != nullptr) {
- const blender::nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration;
+ const nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration;
return !socket_decl.description().is_empty();
}
return false;
}
-static char *node_socket_get_tooltip(const bContext &C,
- const bNodeTree &ntree,
- const bNode &node,
- const bNodeSocket &socket)
+static char *node_socket_get_tooltip(const bContext *C,
+ const bNodeTree *ntree,
+ const bNode *UNUSED(node),
+ const bNodeSocket *socket)
{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ TreeDrawContext tree_draw_ctx;
+ if (snode != nullptr) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ tree_draw_ctx.geo_tree_log = geo_log::GeoModifierLog::get_tree_log_for_node_editor(*snode);
+ }
+ }
+
std::stringstream output;
- if (socket.runtime->declaration != nullptr) {
- const blender::nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration;
+ if (socket->runtime->declaration != nullptr) {
+ const blender::nodes::SocketDeclaration &socket_decl = *socket->runtime->declaration;
blender::StringRef description = socket_decl.description();
if (!description.is_empty()) {
output << TIP_(description.data());
}
}
- if (ntree.type == NTREE_GEOMETRY) {
+ if (ntree->type == NTREE_GEOMETRY && tree_draw_ctx.geo_tree_log != nullptr) {
if (!output.str().empty()) {
output << ".\n\n";
}
std::optional<std::string> socket_inspection_str = create_socket_inspection_string(
- C, node, socket);
+ tree_draw_ctx, *socket);
if (socket_inspection_str.has_value()) {
output << *socket_inspection_str;
}
@@ -1083,37 +1102,46 @@ static char *node_socket_get_tooltip(const bContext &C,
}
if (output.str().empty()) {
- output << nodeSocketLabel(&socket);
+ output << nodeSocketLabel(socket);
}
return BLI_strdup(output.str().c_str());
}
-void node_socket_add_tooltip(const bNodeTree &ntree,
- const bNode &node,
- const bNodeSocket &sock,
- uiLayout &layout)
+static void node_socket_add_tooltip_in_node_editor(TreeDrawContext *UNUSED(tree_draw_ctx),
+ const bNodeTree *ntree,
+ const bNode *node,
+ const bNodeSocket *sock,
+ uiLayout *layout)
{
- if (!node_socket_has_tooltip(ntree, sock)) {
+ if (!node_socket_has_tooltip(*ntree, *sock)) {
return;
}
- SocketTooltipData *data = MEM_new<SocketTooltipData>(__func__);
- data->ntree = &ntree;
- data->node = &node;
- data->socket = &sock;
+ SocketTooltipData *data = MEM_cnew<SocketTooltipData>(__func__);
+ data->ntree = ntree;
+ data->node = node;
+ data->socket = sock;
uiLayoutSetTooltipFunc(
- &layout,
+ layout,
[](bContext *C, void *argN, const char *UNUSED(tip)) {
- const SocketTooltipData *data = static_cast<SocketTooltipData *>(argN);
- return node_socket_get_tooltip(*C, *data->ntree, *data->node, *data->socket);
+ SocketTooltipData *data = static_cast<SocketTooltipData *>(argN);
+ return node_socket_get_tooltip(C, data->ntree, data->node, data->socket);
},
data,
MEM_dupallocN,
MEM_freeN);
}
+void node_socket_add_tooltip(const bNodeTree &ntree,
+ const bNode &node,
+ const bNodeSocket &sock,
+ uiLayout &layout)
+{
+ node_socket_add_tooltip_in_node_editor(nullptr, &ntree, &node, &sock, &layout);
+}
+
static void node_socket_draw_nested(const bContext &C,
bNodeTree &ntree,
PointerRNA &node_ptr,
@@ -1178,7 +1206,7 @@ static void node_socket_draw_nested(const bContext &C,
but,
[](bContext *C, void *argN, const char *UNUSED(tip)) {
SocketTooltipData *data = (SocketTooltipData *)argN;
- return node_socket_get_tooltip(*C, *data->ntree, *data->node, *data->socket);
+ return node_socket_get_tooltip(C, data->ntree, data->node, data->socket);
},
data,
MEM_freeN);
@@ -1607,27 +1635,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char
#define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit)
-static void node_add_error_message_button(
- const bContext &C, bNode &node, uiBlock &block, const rctf &rect, float &icon_offset)
+static void node_add_error_message_button(TreeDrawContext &tree_draw_ctx,
+ bNode &node,
+ uiBlock &block,
+ const rctf &rect,
+ float &icon_offset)
{
- SpaceNode *snode = CTX_wm_space_node(&C);
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode,
- node);
- if (node_log == nullptr) {
- return;
+ Span<geo_log::NodeWarning> warnings;
+ if (tree_draw_ctx.geo_tree_log) {
+ geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name);
+ if (node_log != nullptr) {
+ warnings = node_log->warnings;
+ }
}
-
- Span<geo_log::NodeWarning> warnings = node_log->warnings();
-
if (warnings.is_empty()) {
return;
}
- NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN(
- sizeof(NodeErrorsTooltipData), __func__);
- tooltip_data->warnings = warnings;
-
const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings);
+ NodeErrorsTooltipData *tooltip_data = MEM_new<NodeErrorsTooltipData>(__func__);
+ tooltip_data->warnings = warnings;
icon_offset -= NODE_HEADER_ICON_SIZE;
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
@@ -1645,90 +1672,70 @@ static void node_add_error_message_button(
0,
0,
nullptr);
- UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN);
+ UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, [](void *arg) {
+ MEM_delete(static_cast<NodeErrorsTooltipData *>(arg));
+ });
UI_block_emboss_set(&block, UI_EMBOSS);
}
-static void get_exec_time_other_nodes(const bNode &node,
- const SpaceNode &snode,
- std::chrono::microseconds &exec_time,
- int &node_count)
+static std::optional<std::chrono::nanoseconds> node_get_execution_time(
+ TreeDrawContext &tree_draw_ctx, const bNodeTree &ntree, const bNode &node)
{
- if (node.type == NODE_GROUP) {
- const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
- snode);
- if (root_tree_log == nullptr) {
- return;
- }
- const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node.name);
- if (tree_log == nullptr) {
- return;
- }
- tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
- exec_time += node_log.execution_time();
- node_count++;
- });
+ const geo_log::GeoTreeLog *tree_log = tree_draw_ctx.geo_tree_log;
+ if (tree_log == nullptr) {
+ return std::nullopt;
}
- else {
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
- snode, node);
- if (node_log) {
- exec_time += node_log->execution_time();
- node_count++;
- }
- }
-}
-
-static std::chrono::microseconds node_get_execution_time(const bNodeTree &ntree,
- const bNode &node,
- const SpaceNode &snode,
- int &node_count)
-{
- std::chrono::microseconds exec_time = std::chrono::microseconds::zero();
if (node.type == NODE_GROUP_OUTPUT) {
- const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
- snode);
-
- if (tree_log == nullptr) {
- return exec_time;
- }
- tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
- exec_time += node_log.execution_time();
- node_count++;
- });
+ return tree_log->run_time_sum;
}
- else if (node.type == NODE_FRAME) {
+ if (node.type == NODE_FRAME) {
/* Could be cached in the future if this recursive code turns out to be slow. */
+ std::chrono::nanoseconds run_time{0};
+ bool found_node = false;
LISTBASE_FOREACH (bNode *, tnode, &ntree.nodes) {
if (tnode->parent != &node) {
continue;
}
if (tnode->type == NODE_FRAME) {
- exec_time += node_get_execution_time(ntree, *tnode, snode, node_count);
+ std::optional<std::chrono::nanoseconds> sub_frame_run_time = node_get_execution_time(
+ tree_draw_ctx, ntree, *tnode);
+ if (sub_frame_run_time.has_value()) {
+ run_time += *sub_frame_run_time;
+ found_node = true;
+ }
}
else {
- get_exec_time_other_nodes(*tnode, snode, exec_time, node_count);
+ if (const geo_log::GeoNodeLog *node_log = tree_log->nodes.lookup_ptr_as(tnode->name)) {
+ found_node = true;
+ run_time += node_log->run_time;
+ }
}
}
+ if (found_node) {
+ return run_time;
+ }
+ return std::nullopt;
}
- else {
- get_exec_time_other_nodes(node, snode, exec_time, node_count);
+ if (const geo_log::GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node.name)) {
+ return node_log->run_time;
}
- return exec_time;
+ return std::nullopt;
}
-static std::string node_get_execution_time_label(const SpaceNode &snode, const bNode &node)
+static std::string node_get_execution_time_label(TreeDrawContext &tree_draw_ctx,
+ const SpaceNode &snode,
+ const bNode &node)
{
- int node_count = 0;
- std::chrono::microseconds exec_time = node_get_execution_time(
- *snode.edittree, node, snode, node_count);
+ const std::optional<std::chrono::nanoseconds> exec_time = node_get_execution_time(
+ tree_draw_ctx, *snode.edittree, node);
- if (node_count == 0) {
+ if (!exec_time.has_value()) {
return std::string("");
}
- uint64_t exec_time_us = exec_time.count();
+ const uint64_t exec_time_us =
+ std::chrono::duration_cast<std::chrono::microseconds>(*exec_time).count();
/* Don't show time if execution time is 0 microseconds. */
if (exec_time_us == 0) {
@@ -1763,7 +1770,7 @@ struct NodeExtraInfoRow {
};
struct NamedAttributeTooltipArg {
- Map<std::string, eNamedAttrUsage> usage_by_attribute;
+ Map<std::string, geo_log::NamedAttributeUsage> usage_by_attribute;
};
static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
@@ -1775,7 +1782,7 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char
struct NameWithUsage {
StringRefNull name;
- eNamedAttrUsage usage;
+ geo_log::NamedAttributeUsage usage;
};
Vector<NameWithUsage> sorted_used_attribute;
@@ -1790,16 +1797,16 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char
for (const NameWithUsage &attribute : sorted_used_attribute) {
const StringRefNull name = attribute.name;
- const eNamedAttrUsage usage = attribute.usage;
+ const geo_log::NamedAttributeUsage usage = attribute.usage;
ss << " \u2022 \"" << name << "\": ";
Vector<std::string> usages;
- if ((usage & eNamedAttrUsage::Read) != eNamedAttrUsage::None) {
+ if ((usage & geo_log::NamedAttributeUsage::Read) != geo_log::NamedAttributeUsage::None) {
usages.append(TIP_("read"));
}
- if ((usage & eNamedAttrUsage::Write) != eNamedAttrUsage::None) {
+ if ((usage & geo_log::NamedAttributeUsage::Write) != geo_log::NamedAttributeUsage::None) {
usages.append(TIP_("write"));
}
- if ((usage & eNamedAttrUsage::Remove) != eNamedAttrUsage::None) {
+ if ((usage & geo_log::NamedAttributeUsage::Remove) != geo_log::NamedAttributeUsage::None) {
usages.append(TIP_("remove"));
}
for (const int i : usages.index_range()) {
@@ -1817,7 +1824,7 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char
}
static NodeExtraInfoRow row_from_used_named_attribute(
- const Map<std::string, eNamedAttrUsage> &usage_by_attribute_name)
+ const Map<std::string, geo_log::NamedAttributeUsage> &usage_by_attribute_name)
{
const int attributes_num = usage_by_attribute_name.size();
@@ -1831,32 +1838,11 @@ static NodeExtraInfoRow row_from_used_named_attribute(
return row;
}
-static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const SpaceNode &snode,
- const bNode &node)
+static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(
+ TreeDrawContext &tree_draw_ctx, const bNode &node)
{
- if (node.type == NODE_GROUP) {
- const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
- snode);
- if (root_tree_log == nullptr) {
- return std::nullopt;
- }
- const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node.name);
- if (tree_log == nullptr) {
- return std::nullopt;
- }
-
- Map<std::string, eNamedAttrUsage> usage_by_attribute;
- tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
- for (const geo_log::UsedNamedAttribute &used_attribute : node_log.used_named_attributes()) {
- usage_by_attribute.lookup_or_add_as(used_attribute.name,
- used_attribute.usage) |= used_attribute.usage;
- }
- });
- if (usage_by_attribute.is_empty()) {
- return std::nullopt;
- }
-
- return row_from_used_named_attribute(usage_by_attribute);
+ if (tree_draw_ctx.geo_tree_log == nullptr) {
+ return std::nullopt;
}
if (ELEM(node.type,
GEO_NODE_STORE_NAMED_ATTRIBUTE,
@@ -1865,31 +1851,26 @@ static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const Sp
/* Only show the overlay when the name is passed in from somewhere else. */
LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
if (STREQ(socket->name, "Name")) {
- if ((socket->flag & SOCK_IN_USE) == 0) {
+ if (!socket->is_directly_linked()) {
return std::nullopt;
}
}
}
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
- snode, node.name);
- if (node_log == nullptr) {
- return std::nullopt;
- }
- Map<std::string, eNamedAttrUsage> usage_by_attribute;
- for (const geo_log::UsedNamedAttribute &used_attribute : node_log->used_named_attributes()) {
- usage_by_attribute.lookup_or_add_as(used_attribute.name,
- used_attribute.usage) |= used_attribute.usage;
- }
- if (usage_by_attribute.is_empty()) {
- return std::nullopt;
- }
- return row_from_used_named_attribute(usage_by_attribute);
}
-
- return std::nullopt;
+ tree_draw_ctx.geo_tree_log->ensure_used_named_attributes();
+ geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name);
+ if (node_log == nullptr) {
+ return std::nullopt;
+ }
+ if (node_log->used_named_attributes.is_empty()) {
+ return std::nullopt;
+ }
+ return row_from_used_named_attribute(node_log->used_named_attributes);
}
-static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, const bNode &node)
+static Vector<NodeExtraInfoRow> node_get_extra_info(TreeDrawContext &tree_draw_ctx,
+ const SpaceNode &snode,
+ const bNode &node)
{
Vector<NodeExtraInfoRow> rows;
if (!(snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS)) {
@@ -1898,7 +1879,8 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons
if (snode.overlay.flag & SN_OVERLAY_SHOW_NAMED_ATTRIBUTES &&
snode.edittree->type == NTREE_GEOMETRY) {
- if (std::optional<NodeExtraInfoRow> row = node_get_accessed_attributes_row(snode, node)) {
+ if (std::optional<NodeExtraInfoRow> row = node_get_accessed_attributes_row(tree_draw_ctx,
+ node)) {
rows.append(std::move(*row));
}
}
@@ -1907,7 +1889,7 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons
(ELEM(node.typeinfo->nclass, NODE_CLASS_GEOMETRY, NODE_CLASS_GROUP, NODE_CLASS_ATTRIBUTE) ||
ELEM(node.type, NODE_FRAME, NODE_GROUP_OUTPUT))) {
NodeExtraInfoRow row;
- row.text = node_get_execution_time_label(snode, node);
+ row.text = node_get_execution_time_label(tree_draw_ctx, snode, node);
if (!row.text.empty()) {
row.tooltip = TIP_(
"The execution time from the node tree's latest evaluation. For frame and group nodes, "
@@ -1916,14 +1898,17 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons
rows.append(std::move(row));
}
}
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(snode,
- node);
- if (node_log != nullptr) {
- for (const std::string &message : node_log->debug_messages()) {
- NodeExtraInfoRow row;
- row.text = message;
- row.icon = ICON_INFO;
- rows.append(std::move(row));
+
+ if (snode.edittree->type == NTREE_GEOMETRY && tree_draw_ctx.geo_tree_log != nullptr) {
+ tree_draw_ctx.geo_tree_log->ensure_debug_messages();
+ const geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name);
+ if (node_log != nullptr) {
+ for (const StringRef message : node_log->debug_messages) {
+ NodeExtraInfoRow row;
+ row.text = message;
+ row.icon = ICON_INFO;
+ rows.append(std::move(row));
+ }
}
}
@@ -1988,9 +1973,12 @@ static void node_draw_extra_info_row(const bNode &node,
}
}
-static void node_draw_extra_info_panel(const SpaceNode &snode, const bNode &node, uiBlock &block)
+static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx,
+ const SpaceNode &snode,
+ const bNode &node,
+ uiBlock &block)
{
- Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(snode, node);
+ Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(tree_draw_ctx, snode, node);
if (extra_info_rows.size() == 0) {
return;
@@ -2046,6 +2034,7 @@ static void node_draw_extra_info_panel(const SpaceNode &snode, const bNode &node
}
static void node_draw_basis(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
const View2D &v2d,
const SpaceNode &snode,
bNodeTree &ntree,
@@ -2070,7 +2059,7 @@ static void node_draw_basis(const bContext &C,
GPU_line_width(1.0f);
- node_draw_extra_info_panel(snode, node, block);
+ node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
/* Header. */
{
@@ -2165,7 +2154,7 @@ static void node_draw_basis(const bContext &C,
UI_block_emboss_set(&block, UI_EMBOSS);
}
- node_add_error_message_button(C, node, block, rct, iconofs);
+ node_add_error_message_button(tree_draw_ctx, node, block, rct, iconofs);
/* Title. */
if (node.flag & SELECT) {
@@ -2338,6 +2327,7 @@ static void node_draw_basis(const bContext &C,
}
static void node_draw_hidden(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
const View2D &v2d,
const SpaceNode &snode,
bNodeTree &ntree,
@@ -2353,7 +2343,7 @@ static void node_draw_hidden(const bContext &C,
const int color_id = node_get_colorid(node);
- node_draw_extra_info_panel(snode, node, block);
+ node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
/* Shadow. */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
@@ -2668,6 +2658,7 @@ static void reroute_node_prepare_for_draw(bNode &node)
}
static void node_update_nodetree(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
bNodeTree &ntree,
Span<bNode *> nodes,
Span<uiBlock *> blocks)
@@ -2694,7 +2685,7 @@ static void node_update_nodetree(const bContext &C,
node_update_hidden(node, block);
}
else {
- node_update_basis(C, ntree, node, block);
+ node_update_basis(C, tree_draw_ctx, ntree, node, block);
}
}
}
@@ -2795,6 +2786,7 @@ static void frame_node_draw_label(const bNodeTree &ntree,
}
static void frame_node_draw(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
const ARegion &region,
const SpaceNode &snode,
bNodeTree &ntree,
@@ -2841,7 +2833,7 @@ static void frame_node_draw(const bContext &C,
/* label and text */
frame_node_draw_label(ntree, node, snode);
- node_draw_extra_info_panel(snode, node, block);
+ node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
UI_block_end(&C, &block);
UI_block_draw(&C, &block);
@@ -2895,6 +2887,7 @@ static void reroute_node_draw(
}
static void node_draw(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
ARegion &region,
const SpaceNode &snode,
bNodeTree &ntree,
@@ -2903,7 +2896,7 @@ static void node_draw(const bContext &C,
bNodeInstanceKey key)
{
if (node.type == NODE_FRAME) {
- frame_node_draw(C, region, snode, ntree, node, block);
+ frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block);
}
else if (node.type == NODE_REROUTE) {
reroute_node_draw(C, region, ntree, node, block);
@@ -2911,10 +2904,10 @@ static void node_draw(const bContext &C,
else {
const View2D &v2d = region.v2d;
if (node.flag & NODE_HIDDEN) {
- node_draw_hidden(C, v2d, snode, ntree, node, block);
+ node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, node, block);
}
else {
- node_draw_basis(C, v2d, snode, ntree, node, block, key);
+ node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, node, block, key);
}
}
}
@@ -2922,6 +2915,7 @@ static void node_draw(const bContext &C,
#define USE_DRAW_TOT_UPDATE
static void node_draw_nodetree(const bContext &C,
+ TreeDrawContext &tree_draw_ctx,
ARegion &region,
SpaceNode &snode,
bNodeTree &ntree,
@@ -2946,7 +2940,7 @@ static void node_draw_nodetree(const bContext &C,
}
bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]);
- node_draw(C, region, snode, ntree, *nodes[i], *blocks[i], key);
+ node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key);
}
/* Node lines. */
@@ -2976,7 +2970,7 @@ static void node_draw_nodetree(const bContext &C,
}
bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]);
- node_draw(C, region, snode, ntree, *nodes[i], *blocks[i], key);
+ node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key);
}
}
@@ -3035,8 +3029,17 @@ static void draw_nodetree(const bContext &C,
Array<uiBlock *> blocks = node_uiblocks_init(C, nodes);
- node_update_nodetree(C, ntree, nodes, blocks);
- node_draw_nodetree(C, region, *snode, ntree, nodes, blocks, parent_key);
+ TreeDrawContext tree_draw_ctx;
+ if (ntree.type == NTREE_GEOMETRY) {
+ tree_draw_ctx.geo_tree_log = geo_log::GeoModifierLog::get_tree_log_for_node_editor(*snode);
+ if (tree_draw_ctx.geo_tree_log != nullptr) {
+ tree_draw_ctx.geo_tree_log->ensure_node_warnings();
+ tree_draw_ctx.geo_tree_log->ensure_node_run_time();
+ }
+ }
+
+ node_update_nodetree(C, tree_draw_ctx, ntree, nodes, blocks);
+ node_draw_nodetree(C, tree_draw_ctx, region, *snode, ntree, nodes, blocks, parent_key);
}
/**
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index e328a86b0fd..809c4b2fe59 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -14,6 +14,7 @@
#include "DNA_space_types.h"
#include "BKE_context.h"
+#include "BKE_node_runtime.hh"
#include "BKE_node_tree_update.h"
#include "BKE_object.h"
@@ -30,12 +31,11 @@
#include "UI_interface.hh"
#include "UI_resources.h"
-#include "NOD_geometry_nodes_eval_log.hh"
+#include "NOD_geometry_nodes_log.hh"
#include "node_intern.hh"
-namespace geo_log = blender::nodes::geometry_nodes_eval_log;
-using geo_log::GeometryAttributeInfo;
+using blender::nodes::geo_eval_log::GeometryAttributeInfo;
namespace blender::ed::space_node {
@@ -50,6 +50,8 @@ BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context(
const bContext &C, AttributeSearchData &data)
{
+ using namespace nodes::geo_eval_log;
+
SpaceNode *snode = CTX_wm_space_node(&C);
if (!snode) {
BLI_assert_unreachable();
@@ -65,41 +67,48 @@ static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context(
BLI_assert_unreachable();
return {};
}
+ GeoTreeLog *tree_log = GeoModifierLog::get_tree_log_for_node_editor(*snode);
+ if (tree_log == nullptr) {
+ return {};
+ }
+ tree_log->ensure_socket_values();
/* For the attribute input node, collect attribute information from all nodes in the group. */
if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) {
- const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
- *snode);
- if (tree_log == nullptr) {
- return {};
- }
-
+ tree_log->ensure_existing_attributes();
Vector<const GeometryAttributeInfo *> attributes;
- Set<StringRef> names;
- tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
- for (const geo_log::SocketLog &socket_log : node_log.input_logs()) {
- const geo_log::ValueLog *value_log = socket_log.value();
- if (const geo_log::GeometryValueLog *geo_value_log =
- dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
- for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) {
- if (bke::allow_procedural_attribute_access(attribute.name)) {
- if (names.add(attribute.name)) {
- attributes.append(&attribute);
- }
- }
- }
- }
+ for (const GeometryAttributeInfo *attribute : tree_log->existing_attributes) {
+ if (bke::allow_procedural_attribute_access(attribute->name)) {
+ attributes.append(attribute);
}
- });
+ }
return attributes;
}
-
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
- *snode, data.node_name);
+ GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node->name);
if (node_log == nullptr) {
return {};
}
- return node_log->lookup_available_attributes();
+ Set<StringRef> names;
+ Vector<const GeometryAttributeInfo *> attributes;
+ for (const bNodeSocket *input_socket : node->input_sockets()) {
+ if (input_socket->type != SOCK_GEOMETRY) {
+ continue;
+ }
+ const ValueLog *value_log = tree_log->find_socket_value_log(*input_socket);
+ if (value_log == nullptr) {
+ continue;
+ }
+ if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) {
+ for (const GeometryAttributeInfo &attribute : geo_log->attributes) {
+ if (bke::allow_procedural_attribute_access(attribute.name)) {
+ if (names.add(attribute.name)) {
+ attributes.append(&attribute);
+ }
+ }
+ }
+ }
+ }
+ return attributes;
}
static void attribute_search_update_fn(
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 3290c0ddd87..4703eacdcb9 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -4,6 +4,7 @@
#include "BLI_virtual_array.hh"
#include "BKE_attribute.hh"
+#include "BKE_compute_contexts.hh"
#include "BKE_context.h"
#include "BKE_curves.hh"
#include "BKE_editmesh.h"
@@ -26,7 +27,8 @@
#include "ED_curves_sculpt.h"
#include "ED_spreadsheet.h"
-#include "NOD_geometry_nodes_eval_log.hh"
+#include "NOD_geometry_nodes_lazy_function.hh"
+#include "NOD_geometry_nodes_log.hh"
#include "BLT_translation.h"
@@ -40,8 +42,8 @@
#include "spreadsheet_data_source_geometry.hh"
#include "spreadsheet_intern.hh"
-namespace geo_log = blender::nodes::geometry_nodes_eval_log;
using blender::fn::GField;
+using blender::nodes::geo_eval_log::ViewerNodeLog;
namespace blender::ed::spreadsheet {
@@ -465,19 +467,10 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
}
}
else {
- const geo_log::NodeLog *node_log =
- geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet);
- if (node_log != nullptr) {
- for (const geo_log::SocketLog &input_log : node_log->input_logs()) {
- if (const geo_log::GeometryValueLog *geo_value_log =
- dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) {
- const GeometrySet *full_geometry = geo_value_log->full_geometry();
- if (full_geometry != nullptr) {
- geometry_set = *full_geometry;
- break;
- }
- }
- }
+ if (const ViewerNodeLog *viewer_log =
+ nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet(
+ *sspreadsheet)) {
+ geometry_set = viewer_log->geometry;
}
}
}
@@ -495,27 +488,11 @@ static void find_fields_to_evaluate(const SpaceSpreadsheet *sspreadsheet,
/* No viewer is currently referenced by the context path. */
return;
}
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(
- *sspreadsheet);
- if (node_log == nullptr) {
- return;
- }
- for (const geo_log::SocketLog &socket_log : node_log->input_logs()) {
- const geo_log::ValueLog *value_log = socket_log.value();
- if (value_log == nullptr) {
- continue;
- }
- if (const geo_log::GFieldValueLog *field_value_log =
- dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) {
- const GField &field = field_value_log->field();
- if (field) {
- r_fields.add("Viewer", std::move(field));
- }
- }
- if (const geo_log::GenericValueLog *generic_value_log =
- dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
- GPointer value = generic_value_log->value();
- r_fields.add("Viewer", fn::make_constant_field(*value.type(), value.get()));
+ if (const ViewerNodeLog *viewer_log =
+ nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet(
+ *sspreadsheet)) {
+ if (viewer_log->field) {
+ r_fields.add("Viewer", viewer_log->field);
}
}
}