Blender V5.0
node_geo_set_position.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
6
7#include "BKE_curves.hh"
9#include "BKE_instances.hh"
10#include "BKE_mesh.hh"
11
13
14#include "node_geometry_util.hh"
15
17
19{
20 b.use_custom_socket_order();
21 b.allow_any_socket_order();
22 b.add_input<decl::Geometry>("Geometry").description("Points to modify the positions of");
23 b.add_output<decl::Geometry>("Geometry").propagate_all().align_with_previous();
24 b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
25 b.add_input<decl::Vector>("Position").implicit_field_on_all(NODE_DEFAULT_INPUT_POSITION_FIELD);
26 b.add_input<decl::Vector>("Offset").subtype(PROP_TRANSLATION).field_on_all();
27}
28
29static const auto &get_add_fn()
30{
31 static const auto fn = mf::build::SI2_SO<float3, float3, float3>(
32 "Add",
33 [](const float3 a, const float3 b) { return a + b; },
34 mf::build::exec_presets::AllSpanOrSingle());
35 return fn;
36}
37
38static const auto &get_sub_fn()
39{
40 static const auto fn = mf::build::SI2_SO<float3, float3, float3>(
41 "Add",
42 [](const float3 a, const float3 b) { return a - b; },
43 mf::build::exec_presets::AllSpanOrSingle());
44 return fn;
45}
46
48 const fn::FieldContext &field_context,
49 const Field<bool> &selection_field,
50 const Field<float3> &position_field)
51{
53 field_context,
54 "position",
56 selection_field,
57 position_field);
58}
59
61 const fn::FieldContext &field_context,
62 const Field<bool> &selection_field,
63 const Field<float3> &position_field)
64{
66
67 Vector<StringRef> attribute_names;
68 Vector<GField> fields;
69 attribute_names.append("position");
70 fields.append(position_field);
71
72 if (attributes.contains("handle_right") && attributes.contains("handle_left")) {
74 get_sub_fn(), {position_field, bke::AttributeFieldInput::from<float3>("position")}));
75 for (const StringRef name : {"handle_left", "handle_right"}) {
76 attribute_names.append(name);
79 }
80 }
81
83 attributes, field_context, attribute_names, bke::AttrDomain::Point, selection_field, fields);
85}
86
88 const Field<bool> &selection_field,
89 const Field<float3> &position_field)
90{
91 using namespace blender::bke::greasepencil;
92 for (const int layer_index : grease_pencil.layers().index_range()) {
93 Drawing *drawing = grease_pencil.get_eval_drawing(grease_pencil.layer(layer_index));
94 if (drawing == nullptr || drawing->strokes().is_empty()) {
95 continue;
96 }
98 drawing->strokes_for_write(),
100 selection_field,
101 position_field);
102 drawing->tag_positions_changed();
103 }
104}
105
107 const Field<bool> &selection_field,
108 const Field<float3> &position_field)
109{
110 const bke::InstancesFieldContext context(instances);
111 fn::FieldEvaluator evaluator(context, instances.instances_num());
112 evaluator.set_selection(selection_field);
113
114 /* Use a temporary array for the output to avoid potentially reading from freed memory if
115 * retrieving the transforms has to make a mutable copy (then we can't depend on the user count
116 * of the original read-only data). */
118 evaluator.add_with_destination(position_field, result.as_mutable_span());
119 evaluator.evaluate();
120
121 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
122
123 MutableSpan<float4x4> transforms = instances.transforms_for_write();
124 selection.foreach_index(GrainSize(2048),
125 [&](const int i) { transforms[i].location() = result[i]; });
126}
127
129{
130 GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
131 const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
132 const fn::Field<float3> position_field(
134 {params.extract_input<Field<float3>>("Position"),
135 params.extract_input<Field<float3>>("Offset")}));
136
137 if (Mesh *mesh = geometry.get_mesh_for_write()) {
138 set_points_position(mesh->attributes_for_write(),
140 selection_field,
141 position_field);
142 }
143 if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
144 set_points_position(pointcloud->attributes_for_write(),
145 bke::PointCloudFieldContext(*pointcloud),
146 selection_field,
147 position_field);
148 }
149 if (Curves *curves_id = geometry.get_curves_for_write()) {
150 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
153 selection_field,
154 position_field);
155 }
156 if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) {
157 set_position_in_grease_pencil(*grease_pencil, selection_field, position_field);
158 }
159 if (bke::Instances *instances = geometry.get_instances_for_write()) {
160 set_instances_position(*instances, selection_field, position_field);
161 }
162
163 params.set_output("Geometry", std::move(geometry));
164}
165
166static void node_register()
167{
168 static blender::bke::bNodeType ntype;
169
170 geo_node_type_base(&ntype, "GeometryNodeSetPosition", GEO_NODE_SET_POSITION);
171 ntype.ui_name = "Set Position";
172 ntype.ui_description = "Set the location of each point";
173 ntype.enum_name_legacy = "SET_POSITION";
176 ntype.declare = node_declare;
178}
180
181} // namespace blender::nodes::node_geo_set_position_cc
Low-level operations for curves.
Low-level operations for grease pencil.
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:461
#define GEO_NODE_SET_POSITION
@ NODE_DEFAULT_INPUT_POSITION_FIELD
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_TRANSLATION
Definition RNA_types.hh:261
void append(const T &value)
bool contains(StringRef attribute_id) const
static fn::GField from(std::string name, const CPPType &type, std::optional< std::string > socket_inspection_name=std::nullopt)
MutableAttributeAccessor attributes_for_write()
int instances_num() const
Definition instances.cc:393
MutableSpan< float4x4 > transforms_for_write()
Definition instances.cc:235
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void set_selection(Field< bool > selection)
Definition FN_field.hh:383
IndexMask get_evaluated_selection_as_mask() const
Definition field.cc:817
int add_with_destination(GField field, GVMutableArray dst)
Definition field.cc:738
static std::shared_ptr< FieldOperation > from(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
Definition FN_field.hh:242
void foreach_index(Fn &&fn) const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
bool try_capture_field_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, const StringRef attribute_id, AttrDomain domain, const fn::Field< bool > &selection, const fn::GField &field)
bool try_capture_fields_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, Span< StringRef > attribute_ids, AttrDomain domain, const fn::Field< bool > &selection, Span< fn::GField > fields)
static void set_position_in_grease_pencil(GreasePencil &grease_pencil, const Field< bool > &selection_field, const Field< float3 > &position_field)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void set_curves_position(bke::CurvesGeometry &curves, const fn::FieldContext &field_context, const Field< bool > &selection_field, const Field< float3 > &position_field)
static void set_instances_position(bke::Instances &instances, const Field< bool > &selection_field, const Field< float3 > &position_field)
static void set_points_position(bke::MutableAttributeAccessor attributes, const fn::FieldContext &field_context, const Field< bool > &selection_field, const Field< float3 > &position_field)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
const char * name
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