Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
| Show All 13 Lines | |||||
| namespace blender::nodes::node_geo_curve_trim_cc { | namespace blender::nodes::node_geo_curve_trim_cc { | ||||
| NODE_STORAGE_FUNCS(NodeGeometryCurveTrim) | NODE_STORAGE_FUNCS(NodeGeometryCurveTrim) | ||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE); | b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE); | ||||
| // b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field(); | |||||
| b.add_input<decl::Float>(N_("Start")) | b.add_input<decl::Float>(N_("Start")) | ||||
| .min(0.0f) | .min(0.0f) | ||||
| .max(1.0f) | .max(1.0f) | ||||
| .subtype(PROP_FACTOR) | .subtype(PROP_FACTOR) | ||||
| .make_available([](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_FACTOR; }) | .make_available([](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_FACTOR; }) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_input<decl::Float>(N_("End")) | b.add_input<decl::Float>(N_("End")) | ||||
| .min(0.0f) | .min(0.0f) | ||||
| Show All 29 Lines | static void node_init(bNodeTree * /*tree*/, bNode *node) | ||||
| node->storage = data; | node->storage = data; | ||||
| } | } | ||||
| static void node_update(bNodeTree *ntree, bNode *node) | static void node_update(bNodeTree *ntree, bNode *node) | ||||
| { | { | ||||
| const NodeGeometryCurveTrim &storage = node_storage(*node); | const NodeGeometryCurveTrim &storage = node_storage(*node); | ||||
| const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; | const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; | ||||
| // bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next->next; | |||||
| bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next; | bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next; | ||||
| bNodeSocket *end_fac = start_fac->next; | bNodeSocket *end_fac = start_fac->next; | ||||
| bNodeSocket *start_len = end_fac->next; | bNodeSocket *start_len = end_fac->next; | ||||
| bNodeSocket *end_len = start_len->next; | bNodeSocket *end_len = start_len->next; | ||||
| nodeSetSocketAvailability(ntree, start_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); | nodeSetSocketAvailability(ntree, start_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); | ||||
| nodeSetSocketAvailability(ntree, end_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); | nodeSetSocketAvailability(ntree, end_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); | ||||
| nodeSetSocketAvailability(ntree, start_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH); | nodeSetSocketAvailability(ntree, start_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH); | ||||
| Show All 29 Lines | if (params.node_tree().typeinfo->validate_link(eNodeSocketDatatype(params.other_socket().type), | ||||
| SocketSearchOp{"Start", GEO_NODE_CURVE_SAMPLE_LENGTH}); | SocketSearchOp{"Start", GEO_NODE_CURVE_SAMPLE_LENGTH}); | ||||
| params.add_item(IFACE_("End (Length)"), SocketSearchOp{"End", GEO_NODE_CURVE_SAMPLE_LENGTH}); | params.add_item(IFACE_("End (Length)"), SocketSearchOp{"End", GEO_NODE_CURVE_SAMPLE_LENGTH}); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void geometry_set_curve_trim(GeometrySet &geometry_set, | static void geometry_set_curve_trim(GeometrySet &geometry_set, | ||||
| const GeometryNodeCurveSampleMode mode, | const GeometryNodeCurveSampleMode mode, | ||||
| Field<bool> &selection_field, | |||||
| Field<float> &start_field, | Field<float> &start_field, | ||||
| Field<float> &end_field) | Field<float> &end_field) | ||||
| { | { | ||||
| if (!geometry_set.has_curves()) { | if (!geometry_set.has_curves()) { | ||||
| return; | return; | ||||
| } | } | ||||
| const Curves &src_curves_id = *geometry_set.get_curves_for_read(); | const Curves &src_curves_id = *geometry_set.get_curves_for_read(); | ||||
| const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry); | const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry); | ||||
| if (src_curves.curves_num() == 0) { | if (src_curves.curves_num() == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE}; | bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE}; | ||||
| fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; | fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; | ||||
| evaluator.add(selection_field); | |||||
| evaluator.add(start_field); | evaluator.add(start_field); | ||||
| evaluator.add(end_field); | evaluator.add(end_field); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<float> starts = evaluator.get_evaluated<float>(0); | |||||
| const VArray<float> ends = evaluator.get_evaluated<float>(1); | |||||
| const VArray<bool> cyclic = src_curves.cyclic(); | const IndexMask selection = evaluator.get_evaluated_as_mask(0); | ||||
| const VArray<float> starts = evaluator.get_evaluated<float>(1); | |||||
| const VArray<float> ends = evaluator.get_evaluated<float>(2); | |||||
| /* If node length input is on form [0, 1] instead of [0, length]*/ | if (selection.is_empty()) { | ||||
| const bool normalized_length_lookup = mode == GEO_NODE_CURVE_SAMPLE_FACTOR; | return; | ||||
| /* Stack start + end field. */ | |||||
| Vector<float> length_factors(src_curves.curves_num() * 2); | |||||
| Vector<int64_t> lookup_indices(src_curves.curves_num() * 2); | |||||
| threading::parallel_for(src_curves.curves_range(), 512, [&](IndexRange curve_range) { | |||||
| for (const int64_t curve_i : curve_range) { | |||||
| const bool negative_trim = !cyclic[curve_i] && starts[curve_i] > ends[curve_i]; | |||||
| length_factors[curve_i] = starts[curve_i]; | |||||
| length_factors[curve_i + src_curves.curves_num()] = negative_trim ? starts[curve_i] : | |||||
| ends[curve_i]; | |||||
| lookup_indices[curve_i] = curve_i; | |||||
| lookup_indices[curve_i + src_curves.curves_num()] = curve_i; | |||||
| } | } | ||||
| }); | |||||
| /* Create curve trim lookup table. */ | |||||
| Array<bke::curves::CurvePoint, 12> point_lookups = geometry::lookup_curve_points( | |||||
| src_curves, length_factors, lookup_indices, normalized_length_lookup); | |||||
| bke::CurvesGeometry dst_curves = geometry::trim_curves( | bke::CurvesGeometry dst_curves = geometry::trim_curves( | ||||
| src_curves, | src_curves, selection, starts, ends, mode); | ||||
| src_curves.curves_range().as_span(), | |||||
| point_lookups.as_span().slice(0, src_curves.curves_num()), | |||||
| point_lookups.as_span().slice(src_curves.curves_num(), src_curves.curves_num())); | |||||
| Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves)); | Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves)); | ||||
| bke::curves_copy_parameters(src_curves_id, *dst_curves_id); | bke::curves_copy_parameters(src_curves_id, *dst_curves_id); | ||||
| geometry_set.replace_curves(dst_curves_id); | geometry_set.replace_curves(dst_curves_id); | ||||
| } | } | ||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| { | { | ||||
| const NodeGeometryCurveTrim &storage = node_storage(params.node()); | const NodeGeometryCurveTrim &storage = node_storage(params.node()); | ||||
| const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; | const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; | ||||
| GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); | GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); | ||||
| GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(geometry_set); | GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(geometry_set); | ||||
| // Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); | |||||
| Field<bool> selection_field = fn::make_constant_field<bool>(true); | |||||
| if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) { | if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) { | ||||
| Field<float> start_field = params.extract_input<Field<float>>("Start"); | Field<float> start_field = params.extract_input<Field<float>>("Start"); | ||||
| Field<float> end_field = params.extract_input<Field<float>>("End"); | Field<float> end_field = params.extract_input<Field<float>>("End"); | ||||
| geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | ||||
| geometry_set_curve_trim(geometry_set, mode, start_field, end_field); | geometry_set_curve_trim(geometry_set, mode, selection_field, start_field, end_field); | ||||
| }); | }); | ||||
| } | } | ||||
| else if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) { | else if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) { | ||||
| Field<float> start_field = params.extract_input<Field<float>>("Start_001"); | Field<float> start_field = params.extract_input<Field<float>>("Start_001"); | ||||
| Field<float> end_field = params.extract_input<Field<float>>("End_001"); | Field<float> end_field = params.extract_input<Field<float>>("End_001"); | ||||
| geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | ||||
| geometry_set_curve_trim(geometry_set, mode, start_field, end_field); | geometry_set_curve_trim(geometry_set, mode, selection_field, start_field, end_field); | ||||
| }); | }); | ||||
| } | } | ||||
| params.set_output("Curve", std::move(geometry_set)); | params.set_output("Curve", std::move(geometry_set)); | ||||
| } | } | ||||
| } // namespace blender::nodes::node_geo_curve_trim_cc | } // namespace blender::nodes::node_geo_curve_trim_cc | ||||
| Show All 16 Lines | |||||