diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 6da7576d513..73da3b65ecd 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -6515,6 +6515,8 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) va_list args; uiStringInfo *si; + PointerRNA *opptr = UI_but_operator_ptr_get(but); + const EnumPropertyItem *items = nullptr, *item = nullptr; int totitems; bool free_items = false; @@ -6593,10 +6595,13 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } else if (but->optype) { if (type == BUT_GET_RNA_LABEL) { - tmp = BLI_strdup(WM_operatortype_name(but->optype, but->opptr)); + tmp = BLI_strdup(WM_operatortype_name(but->optype, opptr)); } else { - tmp = WM_operatortype_description(C, but->optype, but->opptr); + bContextStore *previous_ctx = CTX_store_get(C); + CTX_store_set(C, but->context); + tmp = WM_operatortype_description(C, but->optype, opptr); + CTX_store_set(C, previous_ctx); } } else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) { @@ -6679,7 +6684,6 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) int(ui_but_value_get(but)); } else if (but->optype) { - PointerRNA *opptr = UI_but_operator_ptr_get(but); wmOperatorType *ot = but->optype; /* So the context is passed to `itemf` functions. */ diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 447ca0d5b64..4f13e89bbae 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -970,9 +970,9 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + const uint siz3d = GPU_vertformat_attr_add(format3d, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - immUniform1f("size", 4.0f); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); immBegin(GPU_PRIM_POINTS, points_wo.size()); float3 brush_origin_wo = math::transform_point(op_data.curves_to_world_mat, op_data.pos_cu); @@ -990,6 +990,7 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust const float dist_to_point_re = math::distance(pos_re, brush_origin_re); const float alpha = 1.0f - ((dist_to_point_re - dist_to_inner_border_re) / alpha_border_re); + immAttr1f(siz3d, 3.0f); immAttr4f(col3d, 0.9f, 0.9f, 0.9f, alpha); immVertex3fv(pos3d, pos_wo); } diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 0e3e6f0ece9..05b481035ba 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -456,6 +456,22 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven return OPERATOR_FINISHED; } +static char *node_add_group_asset_get_description(struct bContext *C, + struct wmOperatorType * /*op*/, + struct PointerRNA * /*values*/) +{ + bool is_valid; + const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); + if (!is_valid) { + return nullptr; + } + const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&handle); + if (!asset_data.description) { + return nullptr; + } + return BLI_strdup(asset_data.description); +} + void NODE_OT_add_group_asset(wmOperatorType *ot) { ot->name = "Add Node Group Asset"; @@ -464,6 +480,7 @@ void NODE_OT_add_group_asset(wmOperatorType *ot) ot->invoke = node_add_group_asset_invoke; ot->poll = node_add_group_poll; + ot->get_description = node_add_group_asset_get_description; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 80ec3cae492..665e1a35f5a 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -1106,6 +1106,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d) /* -- draw rotation center -- */ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); immUniform1f("size", 7.0f); + immUniform4fv("color", float4(color)); immBegin(GPU_PRIM_POINTS, 1); immAttr4ubv(col, color); immVertex3fv(pos, o); diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 6b12512aea0..cb4171678ff 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -154,6 +154,12 @@ struct RealizeCurveInfo { * curves. */ VArray resolution; + + /** + * The resolution attribute must be filled with the default value if it does not exist on some + * curves. + */ + Span nurbs_weight; }; /** Start indices in the final output curves data-block. */ @@ -208,6 +214,7 @@ struct AllCurvesInfo { bool create_handle_postion_attributes = false; bool create_radius_attribute = false; bool create_resolution_attribute = false; + bool create_nurbs_weight_attribute = false; }; /** Collects all tasks that need to be executed to realize all instances. */ @@ -1160,6 +1167,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate( attributes_to_propagate); attributes_to_propagate.remove("position"); attributes_to_propagate.remove("radius"); + attributes_to_propagate.remove("nurbs_weight"); attributes_to_propagate.remove("resolution"); attributes_to_propagate.remove("handle_right"); attributes_to_propagate.remove("handle_left"); @@ -1221,20 +1229,20 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set, } } - /* Retrieve the radius attribute, if it exists. */ if (attributes.contains("radius")) { curve_info.radius = attributes.lookup("radius", ATTR_DOMAIN_POINT).get_internal_span(); info.create_radius_attribute = true; } - - /* Retrieve the resolution attribute, if it exists. */ + if (attributes.contains("nurbs_weight")) { + curve_info.nurbs_weight = + attributes.lookup("nurbs_weight", ATTR_DOMAIN_POINT).get_internal_span(); + info.create_nurbs_weight_attribute = true; + } curve_info.resolution = curves.resolution(); if (attributes.contains("resolution")) { info.create_resolution_attribute = true; } - - /* Retrieve handle position attributes, if they exist. */ if (attributes.contains("handle_right")) { curve_info.handle_left = attributes.lookup("handle_left", ATTR_DOMAIN_POINT).get_internal_span(); @@ -1256,6 +1264,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options, MutableSpan all_handle_left, MutableSpan all_handle_right, MutableSpan all_radii, + MutableSpan all_nurbs_weights, MutableSpan all_resolutions) { const RealizeCurveInfo &curves_info = *task.curve_info; @@ -1286,14 +1295,20 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options, } } - /* Copy radius attribute with 1.0 default if it doesn't exist. */ + auto copy_point_span_with_default = + [&](const Span src, MutableSpan all_dst, const float value) { + if (src.is_empty()) { + all_dst.slice(dst_point_range).fill(value); + } + else { + all_dst.slice(dst_point_range).copy_from(src); + } + }; if (all_curves_info.create_radius_attribute) { - if (curves_info.radius.is_empty()) { - all_radii.slice(dst_point_range).fill(1.0f); - } - else { - all_radii.slice(dst_point_range).copy_from(curves_info.radius); - } + copy_point_span_with_default(curves_info.radius, all_radii, 1.0f); + } + if (all_curves_info.create_nurbs_weight_attribute) { + copy_point_span_with_default(curves_info.nurbs_weight, all_nurbs_weights, 1.0f); } if (all_curves_info.create_resolution_attribute) { @@ -1386,13 +1401,15 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, ATTR_DOMAIN_POINT); } - /* Prepare radius attribute if necessary. */ SpanAttributeWriter radius; if (all_curves_info.create_radius_attribute) { radius = dst_attributes.lookup_or_add_for_write_only_span("radius", ATTR_DOMAIN_POINT); } - - /* Prepare resolution attribute if necessary. */ + SpanAttributeWriter nurbs_weight; + if (all_curves_info.create_nurbs_weight_attribute) { + nurbs_weight = dst_attributes.lookup_or_add_for_write_only_span("nurbs_weight", + ATTR_DOMAIN_POINT); + } SpanAttributeWriter resolution; if (all_curves_info.create_resolution_attribute) { resolution = dst_attributes.lookup_or_add_for_write_only_span("resolution", @@ -1413,6 +1430,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, handle_left.span, handle_right.span, radius.span, + nurbs_weight.span, resolution.span); } }); @@ -1433,6 +1451,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, point_ids.finish(); radius.finish(); resolution.finish(); + nurbs_weight.finish(); handle_left.finish(); handle_right.finish(); } diff --git a/source/blender/geometry/intern/set_curve_type.cc b/source/blender/geometry/intern/set_curve_type.cc index 44e9d285034..572bd624d45 100644 --- a/source/blender/geometry/intern/set_curve_type.cc +++ b/source/blender/geometry/intern/set_curve_type.cc @@ -308,24 +308,23 @@ static bke::CurvesGeometry convert_curves_to_bezier( dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve(); + bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write(); MutableSpan dst_positions = dst_curves.positions_for_write(); MutableSpan dst_handles_l = dst_curves.handle_positions_left_for_write(); MutableSpan dst_handles_r = dst_curves.handle_positions_right_for_write(); MutableSpan dst_types_l = dst_curves.handle_types_left_for_write(); MutableSpan dst_types_r = dst_curves.handle_types_right_for_write(); - MutableSpan dst_weights = dst_curves.nurbs_weights_for_write(); - bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write(); + Set attributes_to_skip = { + "position", "handle_type_left", "handle_type_right", "handle_right", "handle_left"}; + if (!dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) { + attributes_to_skip.add_new("nurbs_weight"); + } Vector generic_attributes = bke::retrieve_attributes_for_transfer( src_attributes, dst_attributes, ATTR_DOMAIN_MASK_POINT, propagation_info, - {"position", - "handle_type_left", - "handle_type_right", - "handle_right", - "handle_left", - "nurbs_weight"}); + attributes_to_skip); auto catmull_rom_to_bezier = [&](IndexMask selection) { bke::curves::fill_points( @@ -396,7 +395,6 @@ static bke::CurvesGeometry convert_curves_to_bezier( dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_l); bke::curves::fill_points( dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_r); - bke::curves::fill_points(dst_points_by_curve, selection, 0.0f, dst_weights); threading::parallel_for(selection.index_range(), 64, [&](IndexRange range) { for (const int i : selection.slice(range)) { @@ -513,7 +511,7 @@ static bke::CurvesGeometry convert_curves_to_nurbs( "nurbs_weight"}); auto fill_weights_if_necessary = [&](const IndexMask selection) { - if (!src_curves.nurbs_weights().is_empty()) { + if (src_attributes.contains("nurbs_weight")) { bke::curves::fill_points( dst_points_by_curve, selection, 1.0f, dst_curves.nurbs_weights_for_write()); } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 15aab38bed7..b6a1da7d487 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -834,15 +834,21 @@ static void initialize_group_input(NodesModifierData &nmd, } } -static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode) +static const lf::FunctionNode *find_viewer_lf_node(const bNode &viewer_bnode) { - return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree()) - ->mapping.viewer_node_map.lookup(&viewer_bnode); + if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info = + blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree())) { + return lf_graph_info->mapping.viewer_node_map.lookup_default(&viewer_bnode, nullptr); + } + return nullptr; } -static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode) +static const lf::FunctionNode *find_group_lf_node(const bNode &group_bnode) { - return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree()) - ->mapping.group_node_map.lookup(&group_bnode); + if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info = + blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree())) { + return lf_graph_info->mapping.group_node_map.lookup_default(&group_bnode, nullptr); + } + return nullptr; } static void find_side_effect_nodes_for_viewer_path( @@ -888,15 +894,22 @@ static void find_side_effect_nodes_for_viewer_path( if (found_viewer_node == nullptr) { return; } + const lf::FunctionNode *lf_viewer_node = find_viewer_lf_node(*found_viewer_node); + if (lf_viewer_node == nullptr) { + return; + } /* Not only mark the viewer node as having side effects, but also all group nodes it is contained * in. */ - r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), - &find_viewer_lf_node(*found_viewer_node)); + r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_viewer_node); compute_context_builder.pop(); while (!compute_context_builder.is_empty()) { - r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), - &find_group_lf_node(*group_node_stack.pop())); + const lf::FunctionNode *lf_group_node = find_group_lf_node(*group_node_stack.pop()); + if (lf_group_node == nullptr) { + return; + } + + r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_group_node); compute_context_builder.pop(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc index 94b12d9897b..17f0131ac54 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc @@ -80,7 +80,9 @@ static Array calculate_curve_parameters(const bke::CurvesGeometry &curves * - NURBS Curves: Treat the control points as if they were a poly curve, because there * is no obvious mapping from each control point to a specific evaluated point. */ -static Array calculate_point_lengths(const bke::CurvesGeometry &curves) +static Array calculate_point_lengths( + const bke::CurvesGeometry &curves, + const FunctionRef, float)> postprocess_lengths_for_curve) { curves.ensure_evaluated_lengths(); const OffsetIndices points_by_curve = curves.points_by_curve(); @@ -93,26 +95,31 @@ static Array calculate_point_lengths(const bke::CurvesGeometry &curves) threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) { for (const int i_curve : range) { const IndexRange points = points_by_curve[i_curve]; - const Span evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, - cyclic[i_curve]); + const bool is_cyclic = cyclic[i_curve]; + const Span evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, is_cyclic); MutableSpan lengths = result.as_mutable_span().slice(points); lengths.first() = 0.0f; + + float total; switch (types[i_curve]) { case CURVE_TYPE_CATMULL_ROM: { const int resolution = resolutions[i_curve]; for (const int i : IndexRange(points.size()).drop_back(1)) { lengths[i + 1] = evaluated_lengths[resolution * (i + 1) - 1]; } + total = evaluated_lengths.last(); break; } case CURVE_TYPE_POLY: lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1)); + total = evaluated_lengths.last(); break; case CURVE_TYPE_BEZIER: { const Span offsets = curves.bezier_evaluated_offsets_for_curve(i_curve); for (const int i : IndexRange(points.size()).drop_back(1)) { lengths[i + 1] = evaluated_lengths[offsets[i + 1] - 1]; } + total = evaluated_lengths.last(); break; } case CURVE_TYPE_NURBS: { @@ -123,44 +130,44 @@ static Array calculate_point_lengths(const bke::CurvesGeometry &curves) length += math::distance(positions[i], positions[i + 1]); } lengths.last() = length; + if (is_cyclic) { + length += math::distance(positions.first(), positions.last()); + } + total = length; break; } } + postprocess_lengths_for_curve(lengths, total); } }); return result; } +static void convert_lengths_to_factors(MutableSpan lengths, const float total_curve_length) +{ + if (total_curve_length > 0.0f) { + const float factor = 1.0f / total_curve_length; + for (float &value : lengths.drop_front(1)) { + value *= factor; + } + } + else if (lengths.size() == 1) { + /* The curve is a single point. */ + lengths[0] = 0.0f; + } + else { + /* It is arbitrary what to do in those rare cases when all the + * points are in the same position. In this case we are just + * arbitrarily giving a valid + * value in the range based on the point index. */ + for (const int i : lengths.index_range()) { + lengths[i] = i / (lengths.size() - 1.0f); + } + } +} static Array calculate_point_parameters(const bke::CurvesGeometry &curves) { - Array lengths = calculate_point_lengths(curves); - const OffsetIndices points_by_curve = curves.points_by_curve(); - - threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) { - for (const int i_curve : range) { - MutableSpan curve_lengths = lengths.as_mutable_span().slice(points_by_curve[i_curve]); - const float total_length = curve_lengths.last(); - if (total_length > 0.0f) { - const float factor = 1.0f / total_length; - for (float &value : curve_lengths) { - value *= factor; - } - } - else if (curve_lengths.size() == 1) { - /* The curve is a single point. */ - curve_lengths[0] = 0.0f; - } - else { - /* It is arbitrary what to do in those rare cases when all the points are - * in the same position. In this case we are just arbitrarily giving a valid - * value in the range based on the point index. */ - for (const int i : curve_lengths.index_range()) { - curve_lengths[i] = i / (curve_lengths.size() - 1.0f); - } - } - } - }); - return lengths; + return calculate_point_lengths(curves, convert_lengths_to_factors); } class CurveParameterFieldInput final : public bke::CurvesFieldInput { @@ -210,7 +217,8 @@ class CurveLengthParameterFieldInput final : public bke::CurvesFieldInput { { switch (domain) { case ATTR_DOMAIN_POINT: - return VArray::ForContainer(calculate_point_lengths(curves)); + return VArray::ForContainer(calculate_point_lengths( + curves, [](MutableSpan /*lengths*/, const float /*total*/) {})); case ATTR_DOMAIN_CURVE: return VArray::ForContainer(accumulated_lengths_curve_domain(curves)); default: