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:
authorClément Foucault <foucault.clem@gmail.com>2022-04-14 19:31:08 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-04-14 19:31:08 +0300
commit89b9ceaa2e3502a2f36d974ffaecab31c7fb739e (patch)
treefd3f8ead5a247a79ea11e4aacc720843bbc5e2c2
parent0c0b59ecb807d697ea1f3ce60abaa38763f82d48 (diff)
parent66dc4d4efb88ecf2d18bfa08ab9c43b024ebd2fb (diff)
Merge branch 'master' into tmp-new-gpu-codegentmp-new-gpu-codegen
-rw-r--r--release/scripts/startup/bl_ui/space_node.py1
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc7
-rw-r--r--source/blender/blenloader/intern/versioning_300.c12
-rw-r--r--source/blender/blenloader/intern/writefile.c11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc38
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc2
-rw-r--r--source/blender/editors/mask/mask_select.c93
-rw-r--r--source/blender/editors/space_node/node_draw.cc164
-rw-r--r--source/blender/io/alembic/ABC_alembic.h14
-rw-r--r--source/blender/io/alembic/intern/alembic_capi.cc17
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_space.c7
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.cc15
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh3
-rw-r--r--source/blender/nodes/NOD_geometry_nodes_eval_log.hh26
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc4
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc14
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc10
21 files changed, 363 insertions, 85 deletions
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index d7d905cb820..1a6e9f57e75 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -709,6 +709,7 @@ class NODE_PT_overlay(Panel):
if snode.tree_type == 'GeometryNodeTree':
col.separator()
col.prop(overlay, "show_timing", text="Timings")
+ col.prop(overlay, "show_named_attributes", text="Named Attributes")
class NODE_UL_interface_sockets(bpy.types.UIList):
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 44ffd64e475..d3c3f41779a 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -50,7 +50,12 @@ GeometrySet object_get_evaluated_geometry_set(const Object &object)
return geometry_set;
}
if (object.runtime.geometry_set_eval != nullptr) {
- return *object.runtime.geometry_set_eval;
+ GeometrySet geometry_set = *object.runtime.geometry_set_eval;
+ /* Ensure that subdivision is performed on the CPU. */
+ if (geometry_set.has_mesh()) {
+ add_final_mesh_as_geometry_component(object, geometry_set);
+ }
+ return geometry_set;
}
/* Otherwise, construct a new geometry set with the component based on the object type. */
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 95851c0e9ff..ec60183218c 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2677,5 +2677,17 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ /* Enable named attributes overlay in node editor. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
+ if (space->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)space;
+ snode->overlay.flag |= SN_OVERLAY_SHOW_NAMED_ATTRIBUTES;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 490328106ca..2ae660ab1b6 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -611,11 +611,14 @@ static void mywrite_id_begin(WriteData *wd, ID *id)
if (wd->use_memfile) {
wd->mem.current_id_session_uuid = id->session_uuid;
- /* If current next memchunk does not match the ID we are about to write, try to find the
- * correct memchunk in the mapping using ID's session_uuid. */
+ /* If current next memchunk does not match the ID we are about to write, or is not the _first_
+ * one for said ID, try to find the correct memchunk in the mapping using ID's session_uuid. */
+ MemFileChunk *curr_memchunk = wd->mem.reference_current_chunk;
+ MemFileChunk *prev_memchunk = curr_memchunk != NULL ? curr_memchunk->prev : NULL;
if (wd->mem.id_session_uuid_mapping != NULL &&
- (wd->mem.reference_current_chunk == NULL ||
- wd->mem.reference_current_chunk->id_session_uuid != id->session_uuid)) {
+ (curr_memchunk == NULL || curr_memchunk->id_session_uuid != id->session_uuid ||
+ (prev_memchunk != NULL &&
+ (prev_memchunk->id_session_uuid == curr_memchunk->id_session_uuid)))) {
void *ref = BLI_ghash_lookup(wd->mem.id_session_uuid_mapping,
POINTER_FROM_UINT(id->session_uuid));
if (ref != NULL) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index b5945c06ad3..23147b63e27 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -699,7 +699,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
add_relation(init_transform_key, local_transform_key, "Transform Init");
/* Various flags, flushing from bases/collections. */
- build_object_from_layer_relations(object);
+ build_object_layer_component_relations(object);
/* Parenting. */
if (object->parent != nullptr) {
/* Make sure parent object's relations are built. */
@@ -787,7 +787,37 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_parameters(&object->id);
}
-void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
+/* NOTE: Implies that the object has base in the current view layer. */
+void DepsgraphRelationBuilder::build_object_from_view_layer_base(Object *object)
+{
+ /* It is possible to have situation when an object is pulled into the dependency graph in a
+ * few different ways:
+ *
+ * - Indirect driver dependency, which doesn't have a Base (or, Base is unknown).
+ * - Via a base from a view layer (view layer of the graph, or view layer of a set scene).
+ * - Possibly other ways, which are not important for decision making here.
+ *
+ * There needs to be a relation from view layer which has a base with the object so that the
+ * order of flags evaluation is correct (object-level base flags evaluation requires view layer
+ * to be evaluated first).
+ *
+ * This build call handles situation when object comes from a view layer, hence has a base, and
+ * needs a relation from the view layer. Do the relation prior to check of whether the object
+ * relations are built so that the relation is created from every view layer which has a base
+ * with this object. */
+
+ OperationKey view_layer_done_key(
+ &scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ OperationKey object_from_layer_entry_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
+
+ add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
+
+ /* Regular object building. */
+ build_object(object);
+}
+
+void DepsgraphRelationBuilder::build_object_layer_component_relations(Object *object)
{
OperationKey object_from_layer_entry_key(
&object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
@@ -810,10 +840,6 @@ void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
OperationKey synchronize_key(
&object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
-
- OperationKey view_layer_done_key(
- &scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
- add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index e1312c68cea..1ccecc9a3f2 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -200,7 +200,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
Object *object,
Collection *collection);
virtual void build_object(Object *object);
- virtual void build_object_from_layer_relations(Object *object);
+ virtual void build_object_from_view_layer_base(Object *object);
+ virtual void build_object_layer_component_relations(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
virtual void build_object_data_geometry(Object *object);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index f9306620a9d..d723e5beb75 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -81,7 +81,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene,
* do nullptr-pointer check of the base, so it's fine to pass original one. */
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (need_pull_base_into_graph(base)) {
- build_object(base->object);
+ build_object_from_view_layer_base(base->object);
}
}
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 29cd593ce7f..e3c3f1c38a0 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -16,6 +16,9 @@
#include "BKE_context.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "DNA_mask_types.h"
#include "WM_api.h"
@@ -427,7 +430,9 @@ static int box_select_exec(bContext *C, wmOperator *op)
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
+ Mask *mask_orig = CTX_data_edit_mask(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
rcti rect;
rctf rectf;
@@ -436,7 +441,7 @@ static int box_select_exec(bContext *C, wmOperator *op)
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ ED_mask_select_toggle_all(mask_orig, SEL_DESELECT);
changed = true;
}
@@ -447,16 +452,22 @@ static int box_select_exec(bContext *C, wmOperator *op)
ED_mask_point_pos(area, region, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
/* do actual selection */
- LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
- if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+ if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
continue;
}
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
- for (int i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (int i = 0; i < spline_orig->tot_point; i++) {
+ MaskSplinePoint *point = &spline_orig->points[i];
MaskSplinePoint *point_deform = &points_array[i];
/* TODO: handles? */
@@ -471,10 +482,10 @@ static int box_select_exec(bContext *C, wmOperator *op)
}
if (changed) {
- ED_mask_select_flush_all(mask);
+ ED_mask_select_flush_all(mask_orig);
- DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ DEG_id_tag_update(&mask_orig->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask_orig);
return OPERATOR_FINISHED;
}
@@ -517,14 +528,16 @@ static bool do_lasso_select_mask(bContext *C,
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
+ Mask *mask_orig = CTX_data_edit_mask(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
rcti rect;
bool changed = false;
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ ED_mask_select_toggle_all(mask_orig, SEL_DESELECT);
changed = true;
}
@@ -532,16 +545,22 @@ static bool do_lasso_select_mask(bContext *C,
BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* do actual selection */
- LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
- if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+ if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
continue;
}
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
- for (int i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (int i = 0; i < spline_orig->tot_point; i++) {
+ MaskSplinePoint *point = &spline_orig->points[i];
MaskSplinePoint *point_deform = &points_array[i];
/* TODO: handles? */
@@ -572,10 +591,10 @@ static bool do_lasso_select_mask(bContext *C,
}
if (changed) {
- ED_mask_select_flush_all(mask);
+ ED_mask_select_flush_all(mask_orig);
- DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ DEG_id_tag_update(&mask_orig->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask_orig);
}
return changed;
@@ -643,7 +662,9 @@ static int circle_select_exec(bContext *C, wmOperator *op)
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
+ Mask *mask_orig = CTX_data_edit_mask(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
float zoomx, zoomy, offset[2], ellipse[2];
int width, height;
@@ -668,21 +689,27 @@ static int circle_select_exec(bContext *C, wmOperator *op)
WM_gesture_is_modal_first(op->customdata));
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ ED_mask_select_toggle_all(mask_orig, SEL_DESELECT);
changed = true;
}
/* do actual selection */
- LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
- if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+ if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
continue;
}
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
- for (int i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (int i = 0; i < spline_orig->tot_point; i++) {
+ MaskSplinePoint *point = &spline_orig->points[i];
MaskSplinePoint *point_deform = &points_array[i];
if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
@@ -696,10 +723,10 @@ static int circle_select_exec(bContext *C, wmOperator *op)
}
if (changed) {
- ED_mask_select_flush_all(mask);
+ ED_mask_select_flush_all(mask_orig);
- DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ DEG_id_tag_update(&mask_orig->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask_orig);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 013413adfe9..692940d405c 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -75,6 +75,7 @@
using blender::GPointer;
using blender::fn::GField;
namespace geo_log = blender::nodes::geometry_nodes_eval_log;
+using geo_log::NamedAttributeUsage;
extern "C" {
/* XXX interface.h */
@@ -1684,10 +1685,127 @@ static std::string node_get_execution_time_label(const SpaceNode &snode, const b
struct NodeExtraInfoRow {
std::string text;
- const char *tooltip;
int icon;
+ const char *tooltip = nullptr;
+
+ uiButToolTipFunc tooltip_fn = nullptr;
+ void *tooltip_fn_arg = nullptr;
+ void (*tooltip_fn_free_arg)(void *) = nullptr;
+};
+
+struct NamedAttributeTooltipArg {
+ Map<std::string, NamedAttributeUsage> usage_by_attribute;
};
+static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
+{
+ NamedAttributeTooltipArg &arg = *static_cast<NamedAttributeTooltipArg *>(argN);
+
+ std::stringstream ss;
+ ss << TIP_("Accessed attribute names:\n");
+ Vector<std::pair<StringRefNull, NamedAttributeUsage>> sorted_used_attribute;
+ for (auto &&item : arg.usage_by_attribute.items()) {
+ sorted_used_attribute.append({item.key, item.value});
+ }
+ std::sort(sorted_used_attribute.begin(), sorted_used_attribute.end());
+ for (const std::pair<StringRefNull, NamedAttributeUsage> &attribute : sorted_used_attribute) {
+ const StringRefNull name = attribute.first;
+ const NamedAttributeUsage usage = attribute.second;
+ ss << " \u2022 \"" << name << "\": ";
+ Vector<std::string> usages;
+ if ((usage & NamedAttributeUsage::Read) != NamedAttributeUsage::None) {
+ usages.append(TIP_("read"));
+ }
+ if ((usage & NamedAttributeUsage::Write) != NamedAttributeUsage::None) {
+ usages.append(TIP_("write"));
+ }
+ if ((usage & NamedAttributeUsage::Remove) != NamedAttributeUsage::None) {
+ usages.append(TIP_("remove"));
+ }
+ for (const int i : usages.index_range()) {
+ ss << usages[i];
+ if (i < usages.size() - 1) {
+ ss << ", ";
+ }
+ }
+ ss << "\n";
+ }
+ ss << "\n";
+ ss << TIP_(
+ "Attributes with these names used within the group may conflict with existing attributes");
+ return BLI_strdup(ss.str().c_str());
+}
+
+static NodeExtraInfoRow row_from_used_named_attribute(
+ const Map<std::string, NamedAttributeUsage> &usage_by_attribute_name)
+{
+ NodeExtraInfoRow row;
+ row.text = TIP_("Attributes");
+ row.icon = ICON_SPREADSHEET;
+ row.tooltip_fn = named_attribute_tooltip;
+ row.tooltip_fn_arg = new NamedAttributeTooltipArg{usage_by_attribute_name};
+ row.tooltip_fn_free_arg = [](void *arg) { delete static_cast<NamedAttributeTooltipArg *>(arg); };
+ return row;
+}
+
+static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const SpaceNode &snode,
+ 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, NamedAttributeUsage> 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 (ELEM(node.type,
+ GEO_NODE_STORE_NAMED_ATTRIBUTE,
+ GEO_NODE_REMOVE_ATTRIBUTE,
+ GEO_NODE_INPUT_NAMED_ATTRIBUTE)) {
+ /* 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) {
+ 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, NamedAttributeUsage> 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;
+}
+
static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, const bNode &node)
{
Vector<NodeExtraInfoRow> rows;
@@ -1718,6 +1836,14 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons
rows.append(std::move(row));
}
}
+
+ 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)) {
+ rows.append(std::move(*row));
+ }
+ }
+
return rows;
}
@@ -1727,20 +1853,20 @@ static void node_draw_extra_info_row(const bNode &node,
const int row,
const NodeExtraInfoRow &extra_info_row)
{
- uiBut *but_timing = uiDefBut(&block,
- UI_BTYPE_LABEL,
- 0,
- extra_info_row.text.c_str(),
- (int)(rect.xmin + 4.0f * U.dpi_fac + NODE_MARGIN_X + 0.4f),
- (int)(rect.ymin + row * (20.0f * U.dpi_fac)),
- (short)(rect.xmax - rect.xmin),
- (short)NODE_DY,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- "");
+ uiBut *but_text = uiDefBut(&block,
+ UI_BTYPE_LABEL,
+ 0,
+ extra_info_row.text.c_str(),
+ (int)(rect.xmin + 4.0f * U.dpi_fac + NODE_MARGIN_X + 0.4f),
+ (int)(rect.ymin + row * (20.0f * U.dpi_fac)),
+ (short)(rect.xmax - rect.xmin),
+ (short)NODE_DY,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
uiBut *but_icon = uiDefIconBut(&block,
UI_BTYPE_BUT,
@@ -1756,9 +1882,15 @@ static void node_draw_extra_info_row(const bNode &node,
0,
0,
extra_info_row.tooltip);
+ if (extra_info_row.tooltip_fn != NULL) {
+ UI_but_func_tooltip_set(but_icon,
+ extra_info_row.tooltip_fn,
+ extra_info_row.tooltip_fn_arg,
+ extra_info_row.tooltip_fn_free_arg);
+ }
UI_block_emboss_set(&block, UI_EMBOSS);
if (node.flag & NODE_MUTED) {
- UI_but_flag_enable(but_timing, UI_BUT_INACTIVE);
+ UI_but_flag_enable(but_text, UI_BUT_INACTIVE);
UI_but_flag_enable(but_icon, UI_BUT_INACTIVE);
}
}
diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h
index d7d3adefc33..ded3258ff18 100644
--- a/source/blender/io/alembic/ABC_alembic.h
+++ b/source/blender/io/alembic/ABC_alembic.h
@@ -99,15 +99,19 @@ void ABC_get_transform(struct CacheReader *reader,
double time,
float scale);
+typedef struct ABCReadParams {
+ double time;
+ int read_flags;
+ const char *velocity_name;
+ float velocity_scale;
+} ABCReadParams;
+
/* Either modifies existing_mesh in-place or constructs a new mesh. */
struct Mesh *ABC_read_mesh(struct CacheReader *reader,
struct Object *ob,
struct Mesh *existing_mesh,
- double time,
- const char **err_str,
- int read_flags,
- const char *velocity_name,
- float velocity_scale);
+ const ABCReadParams *params,
+ const char **err_str);
bool ABC_mesh_topology_changed(struct CacheReader *reader,
struct Object *ob,
diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc
index fe459ce4370..0d4e1d04db0 100644
--- a/source/blender/io/alembic/intern/alembic_capi.cc
+++ b/source/blender/io/alembic/intern/alembic_capi.cc
@@ -785,20 +785,21 @@ static ISampleSelector sample_selector_for_time(chrono_t time)
Mesh *ABC_read_mesh(CacheReader *reader,
Object *ob,
Mesh *existing_mesh,
- const double time,
- const char **err_str,
- const int read_flag,
- const char *velocity_name,
- const float velocity_scale)
+ const ABCReadParams *params,
+ const char **err_str)
{
AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str);
if (abc_reader == nullptr) {
return nullptr;
}
- ISampleSelector sample_sel = sample_selector_for_time(time);
- return abc_reader->read_mesh(
- existing_mesh, sample_sel, read_flag, velocity_name, velocity_scale, err_str);
+ ISampleSelector sample_sel = sample_selector_for_time(params->time);
+ return abc_reader->read_mesh(existing_mesh,
+ sample_sel,
+ params->read_flags,
+ params->velocity_name,
+ params->velocity_scale,
+ err_str);
}
bool ABC_mesh_topology_changed(CacheReader *reader,
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 1b70d8497b6..838213dd2f3 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1513,6 +1513,7 @@ typedef enum eSpaceNodeOverlay_Flag {
SN_OVERLAY_SHOW_WIRE_COLORS = (1 << 2),
SN_OVERLAY_SHOW_TIMINGS = (1 << 3),
SN_OVERLAY_SHOW_PATH = (1 << 4),
+ SN_OVERLAY_SHOW_NAMED_ATTRIBUTES = (1 << 5),
} eSpaceNodeOverlay_Flag;
typedef struct SpaceNode {
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index d2b8eb203aa..c40a2ed9260 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -7143,6 +7143,13 @@ static void rna_def_space_node_overlay(BlenderRNA *brna)
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Show Tree Path", "Display breadcrumbs for the editor's context");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
+
+ prop = RNA_def_property(srna, "show_named_attributes", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SN_OVERLAY_SHOW_NAMED_ATTRIBUTES);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(
+ prop, "Show Named Attributes", "Show when nodes are using named attributes");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
}
static void rna_def_space_node(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
index 7dbd4c5b260..998fb0a94a3 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
@@ -226,14 +226,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
velocity_scale *= FPS;
}
- result = ABC_read_mesh(mcmd->reader,
- ctx->object,
- mesh,
- time,
- &err_str,
- mcmd->read_flag,
- mcmd->cache_file->velocity_name,
- velocity_scale);
+ ABCReadParams params = {};
+ params.time = time;
+ params.read_flags = mcmd->read_flag;
+ params.velocity_name = mcmd->cache_file->velocity_name;
+ params.velocity_scale = velocity_scale;
+
+ result = ABC_read_mesh(mcmd->reader, ctx->object, mesh, &params, &err_str);
# endif
break;
}
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index 96a1904abdd..bac4d0165e9 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -40,6 +40,7 @@ using fn::FieldInput;
using fn::FieldOperation;
using fn::GField;
using fn::ValueOrField;
+using geometry_nodes_eval_log::NamedAttributeUsage;
using geometry_nodes_eval_log::NodeWarningType;
/**
@@ -342,6 +343,8 @@ class GeoNodeExecParams {
void set_default_remaining_outputs();
+ void used_named_attribute(std::string attribute_name, NamedAttributeUsage usage);
+
private:
/* Utilities for detecting common errors at when using this class. */
void check_input_access(StringRef identifier, const CPPType *requested_type = nullptr) const;
diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
index 16332be5179..1ad859aa47b 100644
--- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
+++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
@@ -170,6 +170,24 @@ struct ValueOfSockets {
destruct_ptr<ValueLog> value;
};
+enum class NamedAttributeUsage {
+ None = 0,
+ Read = 1 << 0,
+ Write = 1 << 1,
+ Remove = 1 << 2,
+};
+ENUM_OPERATORS(NamedAttributeUsage, NamedAttributeUsage::Remove);
+
+struct UsedNamedAttribute {
+ std::string name;
+ NamedAttributeUsage usage;
+};
+
+struct NodeWithUsedNamedAttribute {
+ DNode node;
+ UsedNamedAttribute attribute;
+};
+
class GeoLogger;
class ModifierLog;
@@ -186,6 +204,7 @@ class LocalGeoLogger {
Vector<NodeWithWarning> node_warnings_;
Vector<NodeWithExecutionTime> node_exec_times_;
Vector<NodeWithDebugMessage> node_debug_messages_;
+ Vector<NodeWithUsedNamedAttribute> used_named_attributes_;
friend ModifierLog;
@@ -199,6 +218,7 @@ class LocalGeoLogger {
void log_multi_value_socket(DSocket socket, Span<GPointer> values);
void log_node_warning(DNode node, NodeWarningType type, std::string message);
void log_execution_time(DNode node, std::chrono::microseconds exec_time);
+ void log_used_named_attribute(DNode node, std::string attribute_name, NamedAttributeUsage usage);
/**
* Log a message that will be displayed in the node editor next to the node.
* This should only be used for debugging purposes and not to display information to users.
@@ -278,6 +298,7 @@ class NodeLog {
Vector<SocketLog> output_logs_;
Vector<NodeWarning, 0> warnings_;
Vector<std::string, 0> debug_messages_;
+ Vector<UsedNamedAttribute, 0> used_named_attributes_;
std::chrono::microseconds exec_time_;
friend ModifierLog;
@@ -307,6 +328,11 @@ class NodeLog {
return debug_messages_;
}
+ Span<UsedNamedAttribute> used_named_attributes() const
+ {
+ return used_named_attributes_;
+ }
+
std::chrono::microseconds execution_time() const
{
return exec_time_;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
index f6e2be9119c..6cb9ca642ef 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
@@ -81,11 +81,13 @@ static void node_geo_exec(GeoNodeExecParams params)
const std::string name = params.extract_input<std::string>("Name");
- if (!U.experimental.use_named_attribute_nodes) {
+ if (!U.experimental.use_named_attribute_nodes || name.empty()) {
params.set_default_remaining_outputs();
return;
}
+ params.used_named_attribute(name, NamedAttributeUsage::Read);
+
switch (data_type) {
case CD_PROP_FLOAT:
params.set_output("Attribute_Float", AttributeFieldInput::Create<float>(std::move(name)));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc
index 202241affeb..f46b70c91a9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc
@@ -32,6 +32,8 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
+ params.used_named_attribute(name, NamedAttributeUsage::Remove);
+
std::atomic<bool> attribute_exists = false;
std::atomic<bool> cannot_delete = false;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc
index 1d1446ce1bd..92614d1a31d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc
@@ -127,11 +127,13 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
std::string name = params.extract_input<std::string>("Name");
- if (!U.experimental.use_named_attribute_nodes) {
+ if (!U.experimental.use_named_attribute_nodes || name.empty()) {
params.set_output("Geometry", std::move(geometry_set));
return;
}
+ params.used_named_attribute(name, NamedAttributeUsage::Write);
+
const NodeGeometryStoreNamedAttribute &storage = node_storage(params.node());
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
index 13f38c3352e..378bac894e8 100644
--- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc
+++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
@@ -62,6 +62,13 @@ ModifierLog::ModifierLog(GeoLogger &logger)
NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context, debug_message.node);
node_log.debug_messages_.append(debug_message.message);
}
+
+ for (NodeWithUsedNamedAttribute &node_with_attribute_name :
+ local_logger.used_named_attributes_) {
+ NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context,
+ node_with_attribute_name.node);
+ node_log.used_named_attributes_.append(std::move(node_with_attribute_name.attribute));
+ }
}
}
@@ -486,6 +493,13 @@ void LocalGeoLogger::log_execution_time(DNode node, std::chrono::microseconds ex
node_exec_times_.append({node, exec_time});
}
+void LocalGeoLogger::log_used_named_attribute(DNode node,
+ std::string attribute_name,
+ NamedAttributeUsage usage)
+{
+ used_named_attributes_.append({node, {std::move(attribute_name), usage}});
+}
+
void LocalGeoLogger::log_debug_message(DNode node, std::string message)
{
node_debug_messages_.append({node, std::move(message)});
diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc
index d63a6d11eda..cea3084a418 100644
--- a/source/blender/nodes/intern/node_geometry_exec.cc
+++ b/source/blender/nodes/intern/node_geometry_exec.cc
@@ -23,6 +23,16 @@ void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::strin
local_logger.log_node_warning(provider_->dnode, type, std::move(message));
}
+void GeoNodeExecParams::used_named_attribute(std::string attribute_name,
+ const NamedAttributeUsage usage)
+{
+ if (provider_->logger == nullptr) {
+ return;
+ }
+ LocalGeoLogger &local_logger = provider_->logger->local();
+ local_logger.log_used_named_attribute(provider_->dnode, std::move(attribute_name), usage);
+}
+
void GeoNodeExecParams::check_input_geometry_set(StringRef identifier,
const GeometrySet &geometry_set) const
{