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--source/blender/blenkernel/BKE_geometry_set.hh20
-rw-r--r--source/blender/blenkernel/BKE_object.h3
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc12
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc14
-rw-r--r--source/blender/blenkernel/intern/geometry_component_pointcloud.cc14
-rw-r--r--source/blender/blenkernel/intern/geometry_component_volume.cc14
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc13
-rw-r--r--source/blender/blenkernel/intern/object.c16
-rw-r--r--source/blender/editors/space_node/node_draw.cc22
-rw-r--r--source/blender/editors/space_node/node_edit.c51
-rw-r--r--source/blender/editors/space_node/node_intern.h1
-rw-r--r--source/blender/editors/space_node/node_ops.c1
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc46
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h5
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_space.c5
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc119
18 files changed, 338 insertions, 21 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index ab126ecb152..2ce8ce5749f 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -141,6 +141,12 @@ class GeometryComponent {
/* The returned component should be of the same type as the type this is called on. */
virtual GeometryComponent *copy() const = 0;
+ /* Direct data is everything except for instances of objects/collections.
+ * If this returns true, the geometry set can be cached and is still valid after e.g. modifier
+ * evaluation ends. Instances can only be valid as long as the data they instance is valid. */
+ virtual bool owns_direct_data() const = 0;
+ virtual void ensure_owns_direct_data() = 0;
+
void user_add() const;
void user_remove() const;
bool is_mutable() const;
@@ -315,6 +321,8 @@ struct GeometrySet {
void clear();
+ void ensure_owns_direct_data();
+
/* Utility methods for creation. */
static GeometrySet create_with_mesh(
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
@@ -374,6 +382,9 @@ class MeshComponent : public GeometryComponent {
bool is_empty() const final;
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_MESH;
private:
@@ -404,6 +415,9 @@ class PointCloudComponent : public GeometryComponent {
bool is_empty() const final;
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_POINT_CLOUD;
private:
@@ -444,6 +458,9 @@ class InstancesComponent : public GeometryComponent {
bool is_empty() const final;
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_INSTANCES;
};
@@ -466,5 +483,8 @@ class VolumeComponent : public GeometryComponent {
const Volume *get_for_read() const;
Volume *get_for_write();
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
};
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 0c2c6313dde..6d5638375d6 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -34,6 +34,7 @@ struct Base;
struct BoundBox;
struct Curve;
struct Depsgraph;
+struct GeometrySet;
struct GpencilModifierData;
struct HookGpencilModifierData;
struct HookModifierData;
@@ -69,6 +70,8 @@ void BKE_object_free_curve_cache(struct Object *ob);
void BKE_object_free_derived_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
+void BKE_object_set_preview_geometry_set(struct Object *ob, struct GeometrySet *geometry_set);
+
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
void BKE_object_modifier_gpencil_hook_reset(struct Object *ob,
struct HookGpencilModifierData *hmd);
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 68c551645d2..11526eda762 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -108,6 +108,18 @@ bool InstancesComponent::is_empty() const
return transforms_.size() == 0;
}
+bool InstancesComponent::owns_direct_data() const
+{
+ /* The object and collection instances are not direct data. Instance transforms are direct data
+ * and are always owned. Therefore, instance components always own all their direct data. */
+ return true;
+}
+
+void InstancesComponent::ensure_owns_direct_data()
+{
+ BLI_assert(this->is_mutable());
+}
+
static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
{
using namespace blender;
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index f0f46717744..df451b5db1d 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -157,6 +157,20 @@ bool MeshComponent::is_empty() const
return mesh_ == nullptr;
}
+bool MeshComponent::owns_direct_data() const
+{
+ return ownership_ == GeometryOwnershipType::Owned;
+}
+
+void MeshComponent::ensure_owns_direct_data()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ != GeometryOwnershipType::Owned) {
+ mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
index 32c4ee8a6a6..135de14b4f7 100644
--- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
+++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
@@ -107,6 +107,20 @@ bool PointCloudComponent::is_empty() const
return pointcloud_ == nullptr;
}
+bool PointCloudComponent::owns_direct_data() const
+{
+ return ownership_ == GeometryOwnershipType::Owned;
+}
+
+void PointCloudComponent::ensure_owns_direct_data()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ != GeometryOwnershipType::Owned) {
+ pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/geometry_component_volume.cc b/source/blender/blenkernel/intern/geometry_component_volume.cc
index fd2327e0bf5..94ed07a63de 100644
--- a/source/blender/blenkernel/intern/geometry_component_volume.cc
+++ b/source/blender/blenkernel/intern/geometry_component_volume.cc
@@ -97,4 +97,18 @@ Volume *VolumeComponent::get_for_write()
return volume_;
}
+bool VolumeComponent::owns_direct_data() const
+{
+ return ownership_ == GeometryOwnershipType::Owned;
+}
+
+void VolumeComponent::ensure_owns_direct_data()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ != GeometryOwnershipType::Owned) {
+ volume_ = BKE_volume_copy_for_eval(volume_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 3b027c05f39..fd86f4e550c 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -207,6 +207,19 @@ void GeometrySet::clear()
components_.clear();
}
+/* Make sure that the geometry can be cached. This does not ensure ownership of object/collection
+ * instances. */
+void GeometrySet::ensure_owns_direct_data()
+{
+ for (GeometryComponentType type : components_.keys()) {
+ const GeometryComponent *component = this->get_component_for_read(type);
+ if (!component->owns_direct_data()) {
+ GeometryComponent &component_for_write = this->get_component_for_write(type);
+ component_for_write.ensure_owns_direct_data();
+ }
+ }
+}
+
/* Returns a read-only mesh or null. */
const Mesh *GeometrySet::get_mesh_for_read() const
{
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 1c56312b38b..002071fac30 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1756,6 +1756,10 @@ void BKE_object_free_derived_caches(Object *ob)
BKE_geometry_set_free(ob->runtime.geometry_set_eval);
ob->runtime.geometry_set_eval = NULL;
}
+ if (ob->runtime.geometry_set_preview != NULL) {
+ BKE_geometry_set_free(ob->runtime.geometry_set_preview);
+ ob->runtime.geometry_set_preview = NULL;
+ }
}
void BKE_object_free_caches(Object *object)
@@ -1806,6 +1810,18 @@ void BKE_object_free_caches(Object *object)
}
}
+/* Can be called from multiple threads. */
+void BKE_object_set_preview_geometry_set(Object *ob, struct GeometrySet *geometry_set)
+{
+ static ThreadMutex mutex = BLI_MUTEX_INITIALIZER;
+ BLI_mutex_lock(&mutex);
+ if (ob->runtime.geometry_set_preview != NULL) {
+ BKE_geometry_set_free(ob->runtime.geometry_set_preview);
+ }
+ ob->runtime.geometry_set_preview = geometry_set;
+ BLI_mutex_unlock(&mutex);
+}
+
/**
* Actual check for internal data, not context or flags.
*/
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 07a5dbe1d7b..88234c861a0 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -1404,6 +1404,28 @@ 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 in Node mode");
+ 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.c b/source/blender/editors/space_node/node_edit.c
index 8fdee01f78e..518f5639c93 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -41,6 +41,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -1316,6 +1317,7 @@ 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));
}
@@ -1692,6 +1694,55 @@ void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static void disable_active_preview_on_all_nodes(bNodeTree *ntree)
+{
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ node->flag &= ~NODE_ACTIVE_PREVIEW;
+ }
+}
+
+static int node_active_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ntree = snode->edittree;
+ disable_active_preview_on_all_nodes(ntree);
+ bNode *active_node = nodeGetActive(ntree);
+ active_node->flag |= NODE_ACTIVE_PREVIEW;
+
+ /* Tag for update, so that dependent objects are reevaluated. This is necessary when a
+ * spreadsheet editor displays data from a node. */
+ LISTBASE_FOREACH (wmWindow *, window, &((wmWindowManager *)bmain->wm.first)->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_SPREADSHEET) {
+ SpaceSpreadsheet *sspreadsheet = area->spacedata.first;
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_NODE) {
+ DEG_id_tag_update(&ntree->id, ID_RECALC_COPY_ON_WRITE);
+ ED_area_tag_redraw(area);
+ }
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_active_preview_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle Active Preview";
+ ot->description = "Toggle active preview state of node";
+ ot->idname = "NODE_OT_active_preview_toggle";
+
+ /* callbacks */
+ ot->exec = node_active_preview_toggle_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ****************** Mute operator *********************** */
static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index c0952cbaa42..6f281ee05cc 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -273,6 +273,7 @@ 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_ops.c b/source/blender/editors/space_node/node_ops.c
index e35b444aa11..4168ff2922d 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -57,6 +57,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_preview_toggle);
WM_operatortype_append(NODE_OT_options_toggle);
WM_operatortype_append(NODE_OT_hide_socket_toggle);
+ WM_operatortype_append(NODE_OT_active_preview_toggle);
WM_operatortype_append(NODE_OT_node_copy_color);
WM_operatortype_append(NODE_OT_duplicate);
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
index 7eea6c48676..5e050517710 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
@@ -200,25 +200,7 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
const GeometryComponentType used_component_type)
{
GeometrySet geometry_set;
- if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
- 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) {
- return geometry_set;
- }
- BKE_mesh_wrapper_ensure_mdata(mesh);
- MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
- mesh_component.copy_vertex_group_names_from_object(*object_eval);
- }
- else {
- if (object_eval->runtime.geometry_set_eval != nullptr) {
- /* This does not copy the geometry data itself. */
- geometry_set = *object_eval->runtime.geometry_set_eval;
- }
- }
- }
- else {
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
Object *object_orig = DEG_get_original_object(object_eval);
if (object_orig->type == OB_MESH) {
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
@@ -247,6 +229,30 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
}
}
+ 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) {
+ return geometry_set;
+ }
+ BKE_mesh_wrapper_ensure_mdata(mesh);
+ MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+ mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
+ mesh_component.copy_vertex_group_names_from_object(*object_eval);
+ }
+ else {
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_NODE) {
+ if (object_eval->runtime.geometry_set_preview != nullptr) {
+ geometry_set = *object_eval->runtime.geometry_set_preview;
+ }
+ }
+ else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
+ if (object_eval->runtime.geometry_set_eval != nullptr) {
+ geometry_set = *object_eval->runtime.geometry_set_eval;
+ }
+ }
+ }
+ }
return geometry_set;
}
@@ -377,7 +383,7 @@ static Span<int64_t> filter_mesh_elements_by_selection(const bContext *C,
static GeometryComponentType get_display_component_type(const bContext *C, Object *object_eval)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
- if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
+ if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
return (GeometryComponentType)sspreadsheet->geometry_component_type;
}
if (object_eval->type == OB_POINTCLOUD) {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 7b4788737f8..334d683deff 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -348,6 +348,8 @@ typedef struct bNode {
* composite out nodes when editing tree
*/
#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)
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 686cf2048eb..9822aa4f7e4 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -169,6 +169,11 @@ typedef struct Object_Runtime {
struct GeometrySet *geometry_set_eval;
/**
+ * Data from this geometry set is previewed in the spreadsheet editor.
+ */
+ struct GeometrySet *geometry_set_preview;
+
+ /**
* Mesh structure created during object evaluation.
* It has deformation only modifiers applied on it.
*/
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 46e28c9282d..0ad66c63169 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1889,6 +1889,7 @@ typedef enum eSpaceSpreadsheet_FilterFlag {
typedef enum eSpaceSpreadsheet_ObjectEvalState {
SPREADSHEET_OBJECT_EVAL_STATE_FINAL = 0,
SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
+ SPREADSHEET_OBJECT_EVAL_STATE_NODE = 2,
} eSpaceSpreadsheet_Context;
/* -------------------------------------------------------------------- */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index b6c0bce4342..3590b93620c 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -7365,6 +7365,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_NODE,
+ "NODE",
+ ICON_NONE,
+ "Node",
+ "Use data from the first geometry output of the node tagged for preview"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index 843797e0f72..c7d822e5418 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -43,17 +43,22 @@
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_query.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_node_ui_storage.hh"
+#include "BKE_object.h"
#include "BKE_pointcloud.h"
#include "BKE_screen.h"
#include "BKE_simulation.h"
+#include "BKE_workspace.h"
#include "BLO_read_write.h"
@@ -1088,6 +1093,110 @@ static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> tree
}
}
+static const DTreeContext *find_derived_tree_context_that_matches_tree_path(
+ const SpaceNode &snode, const DerivedNodeTree &tree)
+{
+ const DTreeContext &root_context = tree.root_context();
+ bNodeTree *root_tree_eval = root_context.tree().btree();
+ bNodeTree *root_tree_orig = (bNodeTree *)DEG_get_original_id(&root_tree_eval->id);
+ if (snode.nodetree != root_tree_orig) {
+ return nullptr;
+ }
+
+ const DTreeContext *current_context = &root_context;
+ bool is_first = true;
+ LISTBASE_FOREACH (const bNodeTreePath *, path, &snode.treepath) {
+ if (is_first) {
+ is_first = false;
+ continue;
+ }
+ StringRef parent_node_name = path->node_name;
+ const NodeTreeRef &tree_ref = current_context->tree();
+ const NodeRef *parent_node_ref = nullptr;
+ for (const NodeRef *node_ref : tree_ref.nodes()) {
+ if (node_ref->name() == parent_node_name) {
+ parent_node_ref = node_ref;
+ break;
+ }
+ }
+ if (parent_node_ref == nullptr) {
+ return nullptr;
+ }
+ current_context = current_context->child_context(*parent_node_ref);
+ if (current_context == nullptr) {
+ return nullptr;
+ }
+ }
+ return current_context;
+}
+
+static DNode find_active_preview_node_in_node_editor(const SpaceNode &snode,
+ const DerivedNodeTree &tree)
+{
+ const DTreeContext *context = find_derived_tree_context_that_matches_tree_path(snode, tree);
+ if (context == nullptr) {
+ return {};
+ }
+ const NodeTreeRef &tree_ref = context->tree();
+ for (const NodeRef *node_ref : tree_ref.nodes()) {
+ if (node_ref->bnode()->flag & NODE_ACTIVE_PREVIEW) {
+ return {context, node_ref};
+ }
+ }
+ return {};
+}
+
+static DNode find_active_preview_node_in_all_node_editors(Depsgraph *depsgraph,
+ const DerivedNodeTree &tree)
+{
+ Main *bmain = DEG_get_bmain(depsgraph);
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ 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;
+ DNode preview_node = find_active_preview_node_in_node_editor(*snode, tree);
+ if (!preview_node) {
+ continue;
+ }
+ return preview_node;
+ }
+ }
+ return {};
+}
+
+static DSocket find_preview_socket_in_all_node_editors(Depsgraph *depsgraph,
+ const DerivedNodeTree &tree)
+{
+ DNode preview_node = find_active_preview_node_in_all_node_editors(depsgraph, tree);
+ if (!preview_node) {
+ return {};
+ }
+ for (const SocketRef *socket : preview_node->outputs()) {
+ if (socket->bsocket()->type == SOCK_GEOMETRY) {
+ return {preview_node.context(), socket};
+ }
+ }
+ for (const SocketRef *socket : preview_node->inputs()) {
+ if (socket->bsocket()->type == SOCK_GEOMETRY &&
+ (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) {
+ return {preview_node.context(), socket};
+ }
+ }
+ return {};
+}
+
+static void log_preview_socket_value(const Span<GPointer> values, Object *object)
+{
+ GeometrySet geometry_set = *(const GeometrySet *)values[0].get();
+ geometry_set.ensure_owns_direct_data();
+ BKE_object_set_preview_geometry_set(object, new GeometrySet(std::move(geometry_set)));
+}
+
/**
* Evaluate a node group to compute the output geometry.
* Currently, this uses a fairly basic and inefficient algorithm that might compute things more
@@ -1143,6 +1252,14 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
Vector<DInputSocket> group_outputs;
group_outputs.append({root_context, &socket_to_compute});
+ const DSocket preview_socket = find_preview_socket_in_all_node_editors(ctx->depsgraph, tree);
+
+ auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) {
+ if (socket == preview_socket && nmd->modifier.flag & eModifierFlag_Active) {
+ log_preview_socket_value(values, ctx->object);
+ }
+ };
+
GeometryNodesEvaluator evaluator{group_inputs,
group_outputs,
mf_by_node,
@@ -1150,7 +1267,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
ctx->object,
(ModifierData *)nmd,
ctx->depsgraph,
- {}};
+ log_socket_value};
Vector<GMutablePointer> results = evaluator.execute();
BLI_assert(results.size() == 1);