Blender V5.0
node_geo_input_curve_handles.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_curves.hh"
6
8
10
12{
13 b.add_input<decl::Bool>("Relative")
14 .default_value(false)
15 .supports_field()
17 "Output the handle positions relative to the corresponding control point "
18 "instead of in the local space of the geometry");
19 b.add_output<decl::Vector>("Left").field_source_reference_all();
20 b.add_output<decl::Vector>("Right").field_source_reference_all();
21}
22
24 Field<bool> relative_;
25 bool left_;
26
27 public:
29 : bke::GeometryFieldInput(CPPType::get<float3>(), "Handle"), relative_(relative), left_(left)
30 {
31 }
32
34 const IndexMask &mask) const final
35 {
36 const bke::CurvesGeometry *curves_ptr = context.curves_or_strokes();
37 if (!curves_ptr) {
38 return {};
39 }
40 const bke::CurvesGeometry &curves = *curves_ptr;
41 const bke::AttrDomain domain = context.domain();
42
43 const bke::GeometryFieldContext field_context{context, AttrDomain::Point};
44 fn::FieldEvaluator evaluator(field_context, &mask);
45 evaluator.add(relative_);
46 evaluator.evaluate();
47 const VArray<bool> relative = evaluator.get_evaluated<bool>(0);
48
49 const Span<float3> positions = curves.positions();
50
51 const AttributeAccessor attributes = curves.attributes();
52 StringRef side = left_ ? "handle_left" : "handle_right";
54 side, AttrDomain::Point, {0, 0, 0});
55
56 if (relative.is_single()) {
57 if (relative.get_internal_single()) {
58 Array<float3> output(positions.size());
59 for (const int i : positions.index_range()) {
60 output[i] = handles[i] - positions[i];
61 }
62 return attributes.adapt_domain<float3>(
63 VArray<float3>::from_container(std::move(output)), AttrDomain::Point, domain);
64 }
65 return attributes.adapt_domain<float3>(handles, AttrDomain::Point, domain);
66 }
67
68 Array<float3> output(positions.size());
69 for (const int i : positions.index_range()) {
70 if (relative[i]) {
71 output[i] = handles[i] - positions[i];
72 }
73 else {
74 output[i] = handles[i];
75 }
76 }
77 return attributes.adapt_domain<float3>(
78 VArray<float3>::from_container(std::move(output)), AttrDomain::Point, domain);
79 }
80
82 {
83 relative_.node().for_each_field_input_recursive(fn);
84 }
85
87 {
88 return get_default_hash(relative_, left_);
89 }
90
91 bool is_equal_to(const fn::FieldNode &other) const final
92 {
93 if (const HandlePositionFieldInput *other_handle =
94 dynamic_cast<const HandlePositionFieldInput *>(&other))
95 {
96 return relative_ == other_handle->relative_ && left_ == other_handle->left_;
97 }
98 return false;
99 }
100
101 std::optional<AttrDomain> preferred_domain(
102 const bke::GeometryComponent & /*component*/) const final
103 {
104 return AttrDomain::Point;
105 }
106};
107
109{
110 Field<bool> relative = params.extract_input<Field<bool>>("Relative");
111 Field<float3> left_field{std::make_shared<HandlePositionFieldInput>(relative, true)};
112 Field<float3> right_field{std::make_shared<HandlePositionFieldInput>(relative, false)};
113
114 params.set_output("Left", std::move(left_field));
115 params.set_output("Right", std::move(right_field));
116}
117
118static void node_register()
119{
120 static blender::bke::bNodeType ntype;
122 &ntype, "GeometryNodeInputCurveHandlePositions", GEO_NODE_INPUT_CURVE_HANDLES);
123 ntype.ui_name = "Curve Handle Positions";
124 ntype.ui_description = "Retrieve the position of each Bézier control point's handles";
125 ntype.enum_name_legacy = "INPUT_CURVE_HANDLES";
126 ntype.nclass = NODE_CLASS_INPUT;
129 ntype.declare = node_declare;
131}
133
134} // namespace blender::nodes::node_geo_input_curve_handles_cc
Low-level operations for curves.
#define NODE_CLASS_INPUT
Definition BKE_node.hh:447
#define GEO_NODE_INPUT_CURVE_HANDLES
#define final(a, b, c)
Definition BLI_hash.h:19
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
static VArray from_container(ContainerT container)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
GVArray adapt_domain(const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
Span< float3 > positions() const
AttributeAccessor attributes() const
FieldInput(const CPPType &type, std::string debug_name="")
Definition field.cc:677
int add(GField field, GVArray *varray_ptr)
Definition field.cc:751
const GVArray & get_evaluated(const int field_index) const
Definition FN_field.hh:448
std::optional< AttrDomain > preferred_domain(const bke::GeometryComponent &) const final
GVArray get_varray_for_context(const bke::GeometryFieldContext &context, const IndexMask &mask) const final
void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const final
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static int left
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5396
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362
i
Definition text_draw.cc:230
ParamHandle ** handles