Blender V4.3
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
5#include "BKE_curves.hh"
7#include "BKE_instances.hh"
8#include "BKE_mesh.hh"
9#include "BKE_pointcloud.hh"
10
11#include "node_geometry_util.hh"
12
14
16{
17 b.add_input<decl::Geometry>("Geometry");
18 b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
19 b.add_input<decl::Vector>("Position").implicit_field_on_all(implicit_field_inputs::position);
20 b.add_input<decl::Vector>("Offset").subtype(PROP_TRANSLATION).field_on_all();
21 b.add_output<decl::Geometry>("Geometry").propagate_all();
22}
23
24static const auto &get_add_fn()
25{
26 static const auto fn = mf::build::SI2_SO<float3, float3, float3>(
27 "Add",
28 [](const float3 a, const float3 b) { return a + b; },
29 mf::build::exec_presets::AllSpanOrSingle());
30 return fn;
31}
32
33static const auto &get_sub_fn()
34{
35 static const auto fn = mf::build::SI2_SO<float3, float3, float3>(
36 "Add",
37 [](const float3 a, const float3 b) { return a - b; },
38 mf::build::exec_presets::AllSpanOrSingle());
39 return fn;
40}
41
43 const fn::FieldContext &field_context,
44 const Field<bool> &selection_field,
45 const Field<float3> &position_field)
46{
48 field_context,
49 "position",
51 selection_field,
52 position_field);
53}
54
56 const fn::FieldContext &field_context,
57 const Field<bool> &selection_field,
58 const Field<float3> &position_field)
59{
60 MutableAttributeAccessor attributes = curves.attributes_for_write();
61 if (attributes.contains("handle_right") && attributes.contains("handle_left")) {
63 get_sub_fn(), {position_field, bke::AttributeFieldInput::Create<float3>("position")}));
64 for (const StringRef name : {"handle_left", "handle_right"}) {
66 attributes,
67 field_context,
68 name,
70 selection_field,
73 }
74 }
75 set_points_position(attributes, field_context, selection_field, position_field);
76 curves.calculate_bezier_auto_handles();
77}
78
80 const Field<bool> &selection_field,
81 const Field<float3> &position_field)
82{
83 using namespace blender::bke::greasepencil;
84 for (const int layer_index : grease_pencil.layers().index_range()) {
85 Drawing *drawing = grease_pencil.get_eval_drawing(grease_pencil.layer(layer_index));
86 if (drawing == nullptr || drawing->strokes().points_num() == 0) {
87 continue;
88 }
90 drawing->strokes_for_write(),
92 selection_field,
93 position_field);
94 drawing->tag_positions_changed();
95 }
96}
97
99 const Field<bool> &selection_field,
100 const Field<float3> &position_field)
101{
102 const bke::InstancesFieldContext context(instances);
103 fn::FieldEvaluator evaluator(context, instances.instances_num());
104 evaluator.set_selection(selection_field);
105
106 /* Use a temporary array for the output to avoid potentially reading from freed memory if
107 * retrieving the transforms has to make a mutable copy (then we can't depend on the user count
108 * of the original read-only data). */
109 Array<float3> result(instances.instances_num());
110 evaluator.add_with_destination(position_field, result.as_mutable_span());
111 evaluator.evaluate();
112
113 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
114
115 MutableSpan<float4x4> transforms = instances.transforms_for_write();
116 selection.foreach_index(GrainSize(2048),
117 [&](const int i) { transforms[i].location() = result[i]; });
118}
119
121{
122 GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
123 const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
124 const fn::Field<float3> position_field(
126 {params.extract_input<Field<float3>>("Position"),
127 params.extract_input<Field<float3>>("Offset")}));
128
129 if (Mesh *mesh = geometry.get_mesh_for_write()) {
130 set_points_position(mesh->attributes_for_write(),
132 selection_field,
133 position_field);
134 }
135 if (PointCloud *point_cloud = geometry.get_pointcloud_for_write()) {
136 set_points_position(point_cloud->attributes_for_write(),
137 bke::PointCloudFieldContext(*point_cloud),
138 selection_field,
139 position_field);
140 }
141 if (Curves *curves_id = geometry.get_curves_for_write()) {
142 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
143 set_curves_position(curves,
145 selection_field,
146 position_field);
147 }
148 if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) {
149 set_position_in_grease_pencil(*grease_pencil, selection_field, position_field);
150 }
151 if (bke::Instances *instances = geometry.get_instances_for_write()) {
152 set_instances_position(*instances, selection_field, position_field);
153 }
154
155 params.set_output("Geometry", std::move(geometry));
156}
157
158static void node_register()
159{
160 static blender::bke::bNodeType ntype;
161
162 geo_node_type_base(&ntype, GEO_NODE_SET_POSITION, "Set Position", NODE_CLASS_GEOMETRY);
164 ntype.declare = node_declare;
166}
168
169} // 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:418
General operations for point clouds.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_TRANSLATION
Definition RNA_types.hh:164
static fn::GField Create(std::string name, const CPPType &type, std::optional< std::string > socket_inspection_name=std::nullopt)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void set_selection(Field< bool > selection)
Definition FN_field.hh:385
IndexMask get_evaluated_selection_as_mask() const
Definition field.cc:822
int add_with_destination(GField field, GVMutableArray dst)
Definition field.cc:743
static std::shared_ptr< FieldOperation > Create(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
Definition FN_field.hh:244
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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)
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
void position(const bNode &, void *r_value)
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)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
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