Differential D16029 Diff 56262 source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc
Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #include "BLI_task.hh" | #include "BLI_task.hh" | ||||
| #include "BKE_curves.hh" | #include "BKE_curves.hh" | ||||
| #include "node_geometry_util.hh" | #include "node_geometry_util.hh" | ||||
| namespace blender::nodes { | |||||
| int apply_offset_in_cyclic_range(const IndexRange range, | |||||
| const int start_index, | |||||
| const int offset) | |||||
| { | |||||
| BLI_assert(range.contains(start_index)); | |||||
| const int start_in_range = start_index - range.first(); | |||||
| const int offset_in_range = start_in_range + offset; | |||||
| const int mod_offset = offset_in_range % range.size(); | |||||
| if (mod_offset >= 0) { | |||||
| return range[mod_offset]; | |||||
| } | |||||
| return range.last(-(mod_offset + 1)); | |||||
| } | |||||
| } // namespace blender::nodes | |||||
| namespace blender::nodes::node_geo_input_control_point_neighbors_cc { | namespace blender::nodes::node_geo_input_control_point_neighbors_cc { | ||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Int>(N_("Point Index")) | b.add_input<decl::Int>(N_("Point Index")) | ||||
| .implicit_field(implicit_field_inputs::index) | .implicit_field(implicit_field_inputs::index) | ||||
| .hide_value() | .hide_value() | ||||
| .description( | .description( | ||||
| N_("The index of the control point to evaluate. Defaults to the current index")); | N_("The index of the control point to evaluate. Defaults to the current index")); | ||||
| b.add_input<decl::Int>(N_("Offset")) | b.add_input<decl::Int>(N_("Offset")) | ||||
| .dependent_field() | .dependent_field() | ||||
| .description(N_("The number of control points along the curve to traverse")); | .description(N_("The number of control points along the curve to traverse")); | ||||
| b.add_output<decl::Bool>(N_("Is Valid Offset")) | b.add_output<decl::Bool>(N_("Is Valid Offset")) | ||||
| .field_source() | .field_source() | ||||
| .description(N_("Outputs true if the evaluated control point plus the offset " | .description(N_("Outputs true if the evaluated control point plus the offset " | ||||
| "is a valid index of the original curve")); | "is a valid index of the original curve")); | ||||
| b.add_output<decl::Int>(N_("Point Index")) | b.add_output<decl::Int>(N_("Point Index")) | ||||
| .field_source() | .field_source() | ||||
| .description(N_("The index of the control point plus the offset within the entire " | .description(N_("The index of the control point plus the offset within the entire " | ||||
| "curves data-block")); | "curves data-block")); | ||||
| } | } | ||||
| static int apply_offset_in_cyclic_range(const IndexRange range, | |||||
| const int start_index, | |||||
| const int offset) | |||||
| { | |||||
| BLI_assert(range.contains(start_index)); | |||||
| const int start_in_range = start_index - range.first(); | |||||
| const int offset_in_range = start_in_range + offset; | |||||
| const int mod_offset = offset_in_range % range.size(); | |||||
| if (mod_offset >= 0) { | |||||
| return range[mod_offset]; | |||||
| } | |||||
| return range.last(-(mod_offset + 1)); | |||||
| } | |||||
| static Array<int> build_parent_curves(const bke::CurvesGeometry &curves) | |||||
| { | |||||
| Array<int> parent_curves(curves.points_num()); | |||||
| for (const int i : curves.curves_range()) { | |||||
| parent_curves.as_mutable_span().slice(curves.points_for_curve(i)).fill(i); | |||||
| } | |||||
| return parent_curves; | |||||
| } | |||||
| class ControlPointNeighborFieldInput final : public bke::CurvesFieldInput { | class ControlPointNeighborFieldInput final : public bke::CurvesFieldInput { | ||||
| private: | private: | ||||
| const Field<int> index_; | const Field<int> index_; | ||||
| const Field<int> offset_; | const Field<int> offset_; | ||||
| public: | public: | ||||
| ControlPointNeighborFieldInput(Field<int> index, Field<int> offset) | ControlPointNeighborFieldInput(Field<int> index, Field<int> offset) | ||||
| : CurvesFieldInput(CPPType::get<int>(), "Control Point Neighbors"), | : CurvesFieldInput(CPPType::get<int>(), "Control Point Neighbors"), | ||||
| index_(std::move(index)), | index_(std::move(index)), | ||||
| offset_(std::move(offset)) | offset_(std::move(offset)) | ||||
| { | { | ||||
| category_ = Category::Generated; | category_ = Category::Generated; | ||||
| } | } | ||||
| GVArray get_varray_for_context(const bke::CurvesGeometry &curves, | GVArray get_varray_for_context(const bke::CurvesGeometry &curves, | ||||
| const eAttrDomain domain, | const eAttrDomain domain, | ||||
| const IndexMask mask) const final | const IndexMask mask) const final | ||||
| { | { | ||||
| const VArray<bool> cyclic = curves.cyclic(); | const VArray<bool> cyclic = curves.cyclic(); | ||||
| const Array<int> parent_curves = build_parent_curves(curves); | const Array<int> parent_curves = curves.point_to_curve_map(); | ||||
| const bke::CurvesFieldContext context{curves, domain}; | const bke::CurvesFieldContext context{curves, domain}; | ||||
| fn::FieldEvaluator evaluator{context, &mask}; | fn::FieldEvaluator evaluator{context, &mask}; | ||||
| evaluator.add(index_); | evaluator.add(index_); | ||||
| evaluator.add(offset_); | evaluator.add(offset_); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<int> indices = evaluator.get_evaluated<int>(0); | const VArray<int> indices = evaluator.get_evaluated<int>(0); | ||||
| const VArray<int> offsets = evaluator.get_evaluated<int>(1); | const VArray<int> offsets = evaluator.get_evaluated<int>(1); | ||||
| Show All 31 Lines | OffsetValidFieldInput(Field<int> index, Field<int> offset) | ||||
| category_ = Category::Generated; | category_ = Category::Generated; | ||||
| } | } | ||||
| GVArray get_varray_for_context(const bke::CurvesGeometry &curves, | GVArray get_varray_for_context(const bke::CurvesGeometry &curves, | ||||
| const eAttrDomain domain, | const eAttrDomain domain, | ||||
| const IndexMask mask) const final | const IndexMask mask) const final | ||||
| { | { | ||||
| const VArray<bool> cyclic = curves.cyclic(); | const VArray<bool> cyclic = curves.cyclic(); | ||||
| const Array<int> parent_curves = build_parent_curves(curves); | const Array<int> parent_curves = curves.point_to_curve_map(); | ||||
| const bke::CurvesFieldContext context{curves, domain}; | const bke::CurvesFieldContext context{curves, domain}; | ||||
| fn::FieldEvaluator evaluator{context, &mask}; | fn::FieldEvaluator evaluator{context, &mask}; | ||||
| evaluator.add(index_); | evaluator.add(index_); | ||||
| evaluator.add(offset_); | evaluator.add(offset_); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<int> indices = evaluator.get_evaluated<int>(0); | const VArray<int> indices = evaluator.get_evaluated<int>(0); | ||||
| const VArray<int> offsets = evaluator.get_evaluated<int>(1); | const VArray<int> offsets = evaluator.get_evaluated<int>(1); | ||||
| ▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines | |||||