Blender V4.3
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";
53 VArray<float3> handles = *attributes.lookup_or_default<float3>(
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>::ForContainer(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>::ForContainer(std::move(output)), AttrDomain::Point, domain);
79 }
80
81 void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const final
82 {
83 relative_.node().for_each_field_input_recursive(fn);
84 }
85
86 uint64_t hash() const final
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, GEO_NODE_INPUT_CURVE_HANDLES, "Curve Handle Positions", NODE_CLASS_INPUT);
125 ntype.declare = node_declare;
127}
129
130} // namespace blender::nodes::node_geo_input_curve_handles_cc
Low-level operations for curves.
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define output
static VArray ForContainer(ContainerT container)
int add(GField field, GVArray *varray_ptr)
Definition field.cc:756
const GVArray & get_evaluated(const int field_index) const
Definition FN_field.hh:450
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
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
unsigned __int64 uint64_t
Definition stdint.h:90
Defines a node type.
Definition BKE_node.hh:218
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
NodeDeclareFunction declare
Definition BKE_node.hh:347
ParamHandle ** handles