diff options
Diffstat (limited to 'source/blender')
20 files changed, 362 insertions, 85 deletions
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, ¶ms, &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 { |