32 const bNode *node =
b.node_or_null();
33 b.use_custom_socket_order();
34 b.allow_any_socket_order();
36 b.add_default_layout();
40 "Geometry to evaluate the given fields and store the resulting attributes on. All "
41 "geometry types except volumes are supported");
42 b.add_output<
decl::Geometry>(
"Geometry").propagate_all().align_with_previous();
43 if (node !=
nullptr) {
49 const std::string input_identifier =
51 const std::string output_identifier =
53 b.add_input(data_type, item.name, input_identifier)
56 b.add_output(data_type, item.name, output_identifier).field_on_all().align_with_previous();
62 .align_with_previous();
75 data->domain = int8_t(AttrDomain::Point);
87 C,
"capture_attribute_items",
false,
IFACE_(
"Capture Items")))
90 C, panel,
tree, node);
93 panel->use_property_split_set(
true);
94 panel->use_property_decorate_set(
false);
95 panel->prop(item_ptr,
"data_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
110 if (!attributes.has_value()) {
128 for (
const std::string &unused_id : unused_ids) {
129 attributes->remove(unused_id);
137 if (!
params.output_is_required(
"Geometry")) {
140 TIP_(
"The attribute output cannot be used without the geometry output"));
141 params.set_default_remaining_outputs();
155 const std::string input_identifier =
157 const std::string output_identifier =
159 std::optional<std::string> attribute_id =
params.get_output_anonymous_attribute_id_if_needed(
164 used_attribute_ids_set.
add(*attribute_id);
166 attribute_id_ptrs.
append(std::move(*attribute_id));
171 params.set_output(
"Geometry", geometry_set);
172 params.set_default_remaining_outputs();
178 attribute_ids[
i] = attribute_id_ptrs[
i];
186 params.get_attribute_filter(
"Geometry"), used_attribute_ids_set, component);
190 if (domain == AttrDomain::Instance) {
197 GeometryComponent::Type::PointCloud,
198 GeometryComponent::Type::Curve,
199 GeometryComponent::Type::GreasePencil};
203 if (geometry_set.
has(type)) {
210 params.set_output(
"Geometry", geometry_set);
229 __func__, src_storage);
230 dst_node->
storage = dst_storage;
240 bNode &node =
params.add_node(
"GeometryNodeCaptureAttribute");
241 params.connect_available_socket(node,
"Geometry");
249 bNode &node =
params.add_node(
"GeometryNodeCaptureAttribute");
252 params.update_and_connect_available_socket(node,
params.socket.name);
260 return &node.input_socket(output_socket.index());
277 ntype.
ui_name =
"Capture Attribute";
279 "Store the result of a field on a geometry and output the data as a node socket. Allows "
280 "remembering or interpolating data as the geometry changes, such as positions before "
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_ATTRIBUTE
#define GEO_NODE_CAPTURE_ATTRIBUTE
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
BMesh const char void * data
bool contains(const Key &key) const
void append(const T &value)
IndexRange index_range() const
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
StructureType structure_type
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
bool attribute_name_is_anonymous(const StringRef name)
void node_register_type(bNodeType &ntype)
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)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void foreach_real_geometry(bke::GeometrySet &geometry, FunctionRef< void(bke::GeometrySet &geometry_set)> fn)
static void node_operators()
static void node_free_storage(bNode *node)
static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_init(bNodeTree *, bNode *node)
static void clean_unused_attributes(const AttributeFilter &attribute_filter, const Set< StringRef > &keep, GeometryComponent &component)
static void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_register()
static const bNodeSocket * node_internally_linked_input(const bNodeTree &, const bNode &node, const bNodeSocket &output_socket)
static void node_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
void make_common_operators()
static void draw_items_list_with_operators(const bContext *C, uiLayout *layout, const bNodeTree &tree, const bNode &node)
static void draw_active_item_props(const bNodeTree &tree, const bNode &node, const FunctionRef< void(PointerRNA *item_ptr)> draw_item)
void blend_write(BlendWriter *writer, const bNode &node)
void destruct_array(bNode &node)
void blend_read_data(BlendDataReader *reader, bNode &node)
void copy_array(const bNode &src_node, bNode &dst_node)
Accessor::ItemT * add_item_with_socket_type_and_name(bNodeTree &ntree, bNode &node, const eNodeSocketDatatype socket_type, const char *name, std::optional< int > dimensions=std::nullopt)
bool try_add_item_via_any_extend_socket(bNodeTree &ntree, bNode &extend_node, bNode &storage_node, bNodeLink &link, const std::optional< StringRef > socket_identifier=std::nullopt, typename Accessor::ItemT **r_new_item=nullptr)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
NodeGeometryAttributeCaptureItem * capture_items
bool allow_skip(const StringRef name) const
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
bool has(const GeometryComponent::Type component_type) const
bool has_instances() const
NodeInternallyLinkedInputFunction internally_linked_input
NodeBlendWriteFunction blend_write_storage_content
std::string ui_description
NodeBlendDataReadFunction blend_data_read_storage_content
void(* initfunc)(bNodeTree *ntree, bNode *node)
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
bool(* insert_link)(NodeInsertLinkParams ¶ms)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
void(* register_operators)()
static StructRNA * item_srna
NodeGeometryAttributeCaptureItem ItemT
static std::string input_socket_identifier_for_item(const NodeGeometryAttributeCaptureItem &item)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
static bool supports_socket_type(const eNodeSocketDatatype socket_type, const int)
static std::string output_socket_identifier_for_item(const NodeGeometryAttributeCaptureItem &item)
static void blend_write_item(BlendWriter *writer, const ItemT &item)
void use_property_decorate_set(bool is_sep)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)