/* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BKE_curves.hh" #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_topology_curve_of_point_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_input(N_("Point Index")) .implicit_field(implicit_field_inputs::index) .description(N_("The control point to retrieve data from")); b.add_output(N_("Curve Index")) .dependent_field() .description(N_("The curve the control point is part of")); b.add_output(N_("Index in Curve")) .dependent_field() .description(N_("How far along the control point is along its curve")); } class CurveOfPointInput final : public bke::CurvesFieldInput { public: CurveOfPointInput() : bke::CurvesFieldInput(CPPType::get(), "Point Curve Index") { category_ = Category::Generated; } GVArray get_varray_for_context(const bke::CurvesGeometry &curves, const eAttrDomain domain, const IndexMask /*mask*/) const final { if (domain != ATTR_DOMAIN_POINT) { return {}; } return VArray::ForContainer(curves.point_to_curve_map()); } uint64_t hash() const override { return 413209687345908697; } bool is_equal_to(const fn::FieldNode &other) const override { if (dynamic_cast(&other)) { return true; } return false; } std::optional preferred_domain(const bke::CurvesGeometry & /*curves*/) const final { return ATTR_DOMAIN_POINT; } }; class PointIndexInCurveInput final : public bke::CurvesFieldInput { public: PointIndexInCurveInput() : bke::CurvesFieldInput(CPPType::get(), "Point Index in Curve") { category_ = Category::Generated; } GVArray get_varray_for_context(const bke::CurvesGeometry &curves, const eAttrDomain domain, const IndexMask /*mask*/) const final { if (domain != ATTR_DOMAIN_POINT) { return {}; } const Span offsets = curves.offsets(); Array point_to_curve_map = curves.point_to_curve_map(); return VArray::ForFunc( curves.points_num(), [offsets, point_to_curve_map = std::move(point_to_curve_map)](const int point_i) { const int curve_i = point_to_curve_map[point_i]; return point_i - offsets[curve_i]; }); } uint64_t hash() const final { return 9834765987345677; } bool is_equal_to(const fn::FieldNode &other) const final { if (dynamic_cast(&other)) { return true; } return false; } std::optional preferred_domain(const bke::CurvesGeometry & /*curves*/) { return ATTR_DOMAIN_POINT; } }; static void node_geo_exec(GeoNodeExecParams params) { const Field point_index = params.extract_input>("Point Index"); if (params.output_is_required("Curve Index")) { params.set_output( "Curve Index", Field(std::make_shared( point_index, Field(std::make_shared()), ATTR_DOMAIN_POINT))); } if (params.output_is_required("Index in Curve")) { params.set_output("Index in Curve", Field(std::make_shared( point_index, Field(std::make_shared()), ATTR_DOMAIN_POINT))); } } } // namespace blender::nodes::node_geo_curve_topology_curve_of_point_cc void register_node_type_geo_curve_topology_curve_of_point() { namespace file_ns = blender::nodes::node_geo_curve_topology_curve_of_point_cc; static bNodeType ntype; geo_node_type_base( &ntype, GEO_NODE_CURVE_TOPOLOGY_CURVE_OF_POINT, "Curve of Point", NODE_CLASS_INPUT); ntype.geometry_node_execute = file_ns::node_geo_exec; ntype.declare = file_ns::node_declare; nodeRegisterType(&ntype); }