diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/mask/mask_select.c | 93 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 164 |
2 files changed, 208 insertions, 49 deletions
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); } } |